Flutter - 日志不再裸奔:pd_log 让打印有型、写盘有序

日志不再裸奔:pd_log 让打印有型、写盘有序

一句话简介:pd_log 是一个轻量、跨平台的 Flutter 日志插件,用纯 Dart 统一缓冲写入与文件管理,平台侧提供控制台输出与目录事件监听,既好用又省心。

  • 插件主页:https://pub.dev/packages/pd_log
  • 核心亮点:
    • 级别日志:v/d/i/w/e 五级输出,语义清晰。
    • 统一缓冲写盘:Dart 写线程+定时/阈值刷新,稳健不阻塞。
    • 文件查询与滚动清理:按年/月/日组织,列出/删除/分页检索。
    • 元数据账本:自动维护 NDJSON 事件账本与 JSON 快照。
    • ANSI 样式:控制台彩色输出可开关;文件始终纯文本,安全可靠。
    • 跨平台一致:Web 输出到控制台(不写文件),接口保持一致。

安装与初始化

  • pubspec.yaml 添加依赖:
yaml 复制代码
dependencies:
  pd_log: ^0.7.3
  • 引入与配置:
dart 复制代码
import 'package:pd_log/pd_log.dart';

void main() {
  PDLog.configure(const PDLogConfig(
    minLevel: LogLevel.debug, // 最低输出级别
    ansiEnabled: true,        // 控制台彩色输出(文件始终纯文本)
    nativeFileLoggingEnabled: true, // 开启本地文件写入(Web 端无效)
  ));
  PDLog.i('pd_log is ready');
}
  • Apple 控制台不想要彩色?
dart 复制代码
import 'dart:io';
PDLog.updateConfigure(ansiEnabled: !(Platform.isIOS || Platform.isMacOS));

会用就会爱:核心能力一览

级别日志与标签

dart 复制代码
PDLog.v('Verbose 细节');
PDLog.d('Debug 调试');
PDLog.i('Info 信息');
PDLog.w('Warning 警告');
PDLog.e('Error 错误', tag: 'Network');
  • 建议:按模块使用 tag,定位更精准。

缓冲与刷盘

dart 复制代码
// 通知写线程立即刷盘(平台侧为占位,语义一致)
await PDLog.flushNativeLogs();
  • 适合在应用切后台、退出前调用,确保关键日志落盘。

文件查询与读取

dart 复制代码
// 列出最近的日志文件(支持排序/分页的 ListOptions)
final files = await PDLog.listLogFiles(limit: 20);

// 按年/月列出
final filesByYear = await PDLog.listLogFilesByYear(2025);
final filesByMonth = await PDLog.listLogFilesByYearMonth(2025, 10);

// 读取内容
final path = PDLog.logFilePathIfExists(DateTime.now());
if (path != null) {
  final text = await PDLog.readLogFileContent(path);
  PDLog.d('今日日志长度: ${text.length}');
}

元数据账本与摘要

dart 复制代码
final ledger = await PDLog.metaLedgerContent();   // NDJSON 事件账本
final summary = await PDLog.metaSummaryContent(); // JSON 快照摘要
PDLog.i('Ledger ${ledger.length}, Summary ${summary.length}');
  • 适合做审计与统计,快速把握日志健康度与占用情况。

目录结构自检(可视化助理)

dart 复制代码
final tree = await PDLog.fileTreeString(maxDepth: 4);
print(tree); // 一键打印目录树,排查文件组织是否合理

日志文件存储结构说明

  • 根目录:位于应用可写的本地存储(移动端/桌面端);Web 不写文件,仅控制台输出。
  • 分层组织:通常按"年/月"(可选"日")分层,便于分页与滚动清理。
  • 文件命名:包含日期时间戳与可选模块标识,纯文本 UTF-8,适合备份与检索。
  • 元数据:通过 metaLedgerContent()(NDJSON 账本)与 metaSummaryContent()(JSON 摘要)访问,无需直接关心文件名。
  • 目录巡检:用 fileTreeString(maxDepth: ...) 一键查看树状结构。

示例:

dart 复制代码
final text = await PDLog.fileTreeString(maxDepth: 6);
PDLog.v(text);

输出结果

text 复制代码
/data/user/0/com.example.pd_log_example/files/pd_log
├── .pd_log_meta/
├── pd_log_ledger.jsonl (5322 B)
└── pd_log_summary.json (2582 B)
└── 2025/
    ├── 10/
    │   ├── 15.log (369 B)
    │   ├── 16.log (267 B)
    │   ├── 20.log (16266 B)
    │   └── 28.log (5451 B)
    └── 11/
        └── 03.log (80 B)
  • 保留周期建议:保留最近 90 天,结合 listLogFilesByYear/Month 做滚动清理。
  • 合规建议:敏感信息脱敏;为日志目录设置合理权限与备份策略。

典型场景配方(打工人的快乐来自少走弯路)

  • 接入即稳:统一在 main() 配置 PDLogConfig,确保所有模块都有一致行为。
  • 网络层:请求成功用 i,失败用 w/e 搭配 tag: 'HTTP';重要参数用 JSON 美化打印。
  • 任务执行:阶段打点用 d/i,异常用 e;必要时 flushNativeLogs() 保证落盘。
  • 日志清理:结合 listLogFilesByYear/Month 做滚动清理(如保留最近 N 月),避免空间被"日志怪兽"吃掉。
  • Web 平台:只输出到控制台,不执行文件写入;用统一接口写更少条件判断。
  • 彩色语义:本地开发开 ansiEnabled,CI 或 Apple 控制台关彩色,读取更清晰。

风格与礼仪(让日志说人话)

  • 级别分工:
    • v 细枝末节(大量输出、仅开发环境);
    • d 调试信息(模块内部行为);
    • i 业务关键路径(成功、状态变更);
    • w 非致命异常(降级、重试);
    • e 致命错误(影响功能、需告警)。
  • JSON 美化:序列化对象时尽量结构化输出,避免"猜谜题"。
  • 上下文带上 tag:组件、页面、模块名,让检索更快乐。
  • 慎重输出敏感信息:对账户/隐私数据做脱敏或摘要,符合合规要求。

与其它工具配合更香

  • 与崩溃上报(如 Sentry)组合:e 级别触发上报,普通 i/d 留在本地做排障。
  • 与限流防抖(如 pd_cooldown)组合:把重复点击与日志洪水一起拦住,后端同事给你点赞。

常见问答(FAQ)

  • Q:Web 会写文件吗?
    • A:不会。Web 端只输出到控制台,但接口一致,逻辑更简单。
  • Q:ANSI 彩色会影响文件内容吗?
    • A:不会。文件写入始终是纯文本;彩色只作用于控制台输出。
  • Q:缓冲写盘是不是"拖延症"?
    • A:是"有计划的高效"。写线程+定时/阈值刷新,在性能与可靠性之间拿捏到位。
  • Q:如何做滚动清理?
    • A:用 listLogFilesByYear/Month 拿到文件集合,结合时间策略批量删除即可。
  • Q:我想看目录结构全貌?
    • A:fileTreeString(maxDepth: ...) 一键打印目录树,直观又省事。

小结与彩蛋

  • 总结:pd_log 把日志这件事做得"稳、准、轻",让你专注写功能,不再与日志系统"搏斗"。
  • 彩蛋:把 ANSI 彩色合理开关、文件滚动清理配置好------你的磁盘和眼睛都会感谢你。

实战故事集(让日志"说书")

  • 场景一:用户说"卡了",开发说"我没改",日志说"你们都别吵"。
    • 入口层 i 打点(页面进入/按钮点击),服务层 d 打点(请求开始/结束),异常用 w/e,一条时间线串到底------谁"卡",一目了然。
  • 场景二:凌晨两点的报警电话。
    • 快速打开最近日志文件,定位 e 级别条目,结合 tag: 'HTTP' 或模块名,十分钟搞定根因,回去继续睡。
  • 场景三:新同事刚上手,觉得项目像"迷宫"。
    • 给他看 fileTreeString(maxDepth: 4) 的目录树,以及 metaSummaryContent() 的摘要:从"迷宫"到"景区地图"。

进阶姿势(把日志练到"内功心法")

  • 结构化优先:直接打印对象(如 Map/toJson()),pd_log 会优雅美化,别用拼字符串让自己"猜谜题"。

    • 示例:

      dart 复制代码
      final user = {'id': 42, 'name': 'Ada', 'vip': true};
      PDLog.i(user); // 结构化更友好,后续检索也更舒服
  • 合理采样:高频事件只记录"每 N 次一次",既保留趋势又不灌爆磁盘。

    • 示例:

      dart 复制代码
      int _counter = 0;
      void logSampled(dynamic message) {
        _counter++;
        if (_counter % 10 == 0) PDLog.d('[sampled x10] $message');
      }
  • 账本与摘要:

    • metaLedgerContent() 看"流水账",用 metaSummaryContent() 看"年度总结"。两者配合,既能查细节,也能看全局健康度。
  • 刷盘策略:

    • 切后台、崩溃前、重要里程碑后,调用 flushNativeLogs(),关键时刻不丢证据。
  • 滚动清理:

    • 每月或每周定期清理旧日志。先用 listLogFilesByYear/Month 找到目标,再按时间策略删除(避免成为"日志收藏家")。

常见故障排查(五分钟速通)

  • 看不到文件?
    • 检查 nativeFileLoggingEnabled 是否开启;Web 端本来就只输出控制台(不写文件)。
  • 控制台"彩虹"太炫影响阅读?
    • 关闭 ansiEnabled 或在 Apple 平台按需关闭。
  • 日志"突然不见"?
    • 检查 minLevel,可能被过滤了;或进程退出过快,补一个 flushNativeLogs()
  • 内容太碎,检索费劲?
    • 统一 tag 约定:模块名/页面名/服务名,形成检索维度。
  • 文件太大,磁盘喊疼?
    • 做滚动清理,配合采样与级别过滤。

团队约定清单(可打印贴墙)

  • 级别使用:v(细节,仅开发)、d(调试)、i(业务关键)、w(降级/重试)、e(致命错误)。
  • 结构化输出:优先 toJson()/Map,少拼接字符串。
  • Tag 规则:<层级>/<模块>/<动作>(例如:UI/Profile/Save)。
  • 敏感信息:统一脱敏,不打印原文(账号、手机号、Token 等)。
  • 刷盘节点:切后台、退出、重要节点后主动刷盘。
  • 清理频率:每月一次,保留最近 90 天。
  • Web 差异:只在控制台看日志,不追文件。

术语小抄(跟 PM 也能聊明白)

  • 缓冲写盘:不是"拖延",是"有序"。降低频繁 IO 的性能损耗。
  • 账本与摘要:账本讲细节,摘要讲趋势------像记账和年终复盘。
  • ANSI 彩色:给眼睛减压的调味料,文件仍是朴素纯文本。

彩蛋续集(加点"梗"更耐看)

  • 把日志级别比作辣度:v 微辣、d 中辣、i 重口、w 冒汗、e 冒烟。该出手时才出手,别一把辣椒糊脸。
  • 目录树像森林地图:fileTreeString 就是无人机航拍,一眼看穿小路与主干。
  • 账本是流水席,摘要是菜单推荐:到底吃了啥,一清二楚。

参考资料

相关推荐
申阳6 小时前
Day 3:01. 基于Nuxt开发个人呢博客项目-初始化项目
前端·后端·程序员
三小河6 小时前
解决 React + SSE 流式输出卡顿:Nginx 关键配置实战
前端·架构·前端框架
QuantumLeap丶6 小时前
《Flutter全栈开发实战指南:从零到高级》- 09 -常用UI组件库实战
flutter·ios·dart
玖月晴空6 小时前
Uniapp 速查文档
前端·微信小程序·uni-app
琉-璃6 小时前
vue3+ts 任意组件间的通信 mitt的使用
前端·javascript·vue.js
FogLetter6 小时前
React Fiber 机制:让渲染变得“有礼貌”的魔法
前端·react.js
不想说话的麋鹿6 小时前
「项目前言」从配置程序员到动手造轮子:我用Vue3+NestJS复刻低代码平台的初衷
前端·程序员·全栈
JunpengHu7 小时前
esri-leaflet介绍
前端
zm4357 小时前
bpmn.js 自定义绘制流程图节点
前端·bpmn-js