pd_log

一个为 Flutter 提供跨平台、可缓冲文件写入的日志插件。

pd_log 旨在在不同平台(Android / iOS / macOS / Windows / Linux / Web)上提供一致的日志能力:

  • 支持控制台打印与原生侧日志透传;
  • 原生平台(Android / iOS / macOS / Windows / Linux)支持文件日志缓冲与定时/阈值刷新,提升性能与减少磁盘写入次数;
  • 支持日志级别、标签、时间戳与可选调用者函数信息;
  • 提供日志文件枚举、大小统计与删除能力;
  • 统一的 Dart API,简单易用。

安装

  • pubspec.yaml 中添加依赖(建议使用最新稳定版本):
dependencies:
  pd_log: ^0.5.0
  • 执行 flutter pub get

快速开始

import 'package:pd_log/pd_log.dart';

void main() {
  // 配置日志(可根据需要修改各项配置)
  PDLog.configure(const PDLogConfig(
    defaultTag: 'MyApp',
    minLevel: LogLevel.debug,
    useNative: true,
    useConsole: true,
    showTimestamp: true,
    showCaller: false,
    nativeFileLoggingEnabled: true, // 启用原生文件日志缓冲
    nativeFileLoggingFlushIntervalMs: 2000, // 定时刷新间隔(毫秒)
    nativeFileLoggingMaxBufferEntries: 100, // 缓冲最大条数
    nativeFileLoggingMaxBufferBytes: 64 * 1024, // 缓冲最大字节数
  ));

  // 输出日志
  PDLog.d('App started');
  PDLog.i({'event': 'login', 'user': 'alice'});
  PDLog.e('Something went wrong', tag: 'Network');

  // 增量更新配置(仅修改传入字段)
  PDLog.updateConfigure(useConsole: false, nativeFileLoggingEnabled: true);

  // 手动触发原生侧刷新,确保缓冲内容落盘
  PDLog.flushNativeLogs();
}

配置项说明(PDLogConfig)

  • enabled:是否启用日志(默认 true)。
  • minLevel:最小输出级别(默认 LogLevel.debug)。
  • defaultTag:默认标签(可选)。
  • useNative:是否透传到原生日志系统(默认 true)。
  • useConsole:是否在 Dart 控制台打印(默认 true,仅 kDebugMode 下生效)。
  • showTimestamp:是否在输出中加入时间戳(默认 true)。
  • showCaller:是否显示调用者函数信息(默认 false,开启有少量性能开销)。
    • 说明:从 0.2.1 起,调用者信息通过 package:stack_trace 解析,能够稳定展示 函数名 @ 文件:行号,例如:MyPage._onInfoPressed @ example/lib/main.dart:221
  • nativeFileLoggingEnabled:是否启用原生文件日志缓冲(默认 false)。
  • nativeFileLoggingFlushIntervalMs:定时刷新间隔(毫秒)。
  • nativeFileLoggingMaxBufferEntries:最大缓冲条数(达到阈值触发刷新)。
  • nativeFileLoggingMaxBufferBytes:最大缓冲字节数(达到阈值触发刷新)。
  • logStyles: 全局的日志样式(可指定不同级别的日志输出颜色和字体样式).

常用 API

  • 级别日志:PDLog.v/d/i/w/e(Object? message, {String? tag})
  • 手动刷新原生日志缓冲:PDLog.flushNativeLogs()
  • 获取日志根目录:PDLog.logRootPath()
  • 列出日志文件:PDLog.listLogFiles()(返回 List<PDLogFile>
  • 删除日志:PDLog.deleteLogFile(path)PDLog.deleteAllLogFiles()
  • 列出年份文件夹(原生实现):PDLog.listYearFolders()
  • 按日期检查文件存在并返回路径:PDLog.logFilePathIfExists(DateTime date)
  • 按年列出日志文件:PDLog.listLogFilesByYear(int year)
  • 按年+月列出日志文件:PDLog.listLogFilesByYearMonth(int year, int month)

API 文档注释

本插件的 Dart 源码已补充完整的文档注释(///),涵盖核心类与方法,包括:

  • PDLog:日志输出、原生桥接、文件查询;
  • LogQuery:跨平台路径计算与查询过滤;
  • LogUtils:格式化、颜色样式与 JSON 美化打印。

可在 IDE 中悬浮查看方法说明与参数含义,或使用 Dartdoc 生成离线文档。

JSON 美化打印

当你希望以更易读的方式输出复杂的 Map/List/对象结构(含缩进与换行),可以使用:

PDLog.formated({
  'user': 'alice',
  'items': [1, 2, 3],
  'meta': {
    1: 'index', // 非字符串键将被规范化为字符串,符合 JSON 规范
    'time': DateTime.now(),
  }
});

说明:

  • formated 会生成合法 JSON 文本并透传至原生侧(useNative: true),在包含多行时逐行保持 ANSI 样式;Dart 控制台打印在该方法中默认关闭(避免重复输出)。
  • 非字符串 Map 键会转换为字符串以符合 JSON 规范;如需保留键类型语义,可在业务侧采用自定义格式或 [{key, keyType, value}] 的结构。

自定义输出(覆盖全局配置)

在少数情况下,你可能希望临时覆盖全局配置进行输出:

PDLog.out(
  '自定义的错误警告输出: Customize pressed ',
  tag: '自定义输出',
  useConsole: false,
  useNative: true,
  toFile: true,
  showTimestamp: true,
  style: LogStyleConfig(
    foreground: 34, // 蓝色
    background: 47, // 白底
    styles: [1, 4, 5],    // 粗体, 下划线, 闪烁
  ),
);

文件日志与缓冲策略

当启用 nativeFileLoggingEnabled 后,日志内容将会被透传到原生层,并由各平台的高性能缓冲与写入线程处理:

  • 采用写线程与队列/条件变量避免主线程阻塞;
  • 根据时间间隔与缓冲阈值触发刷新;
  • 写入失败时,原生侧会安全地回填缓冲并重试,最大限度避免日志丢失。

提示:Web 平台不支持原生文件写入,toFile 与文件相关 API 为 no-op;控制台输出与样式应用保持一致。

日志文件滚动策略

支持配置滚动策略,默认不滚动(永久保留)。当启用滚动后,将自动删除早于阈值的旧日志文件。

  • 策略枚举:LogRetentionStrategy.none | days | months | years
  • 配置项:
    • PDLogConfig.logRetentionStrategy(默认 none
    • PDLogConfig.logRetentionCount(保留的数量,单位由策略决定)

示例:只保留最近 7 天的日志(按天滚动):

PDLog.updateConfigure(
  nativeFileLoggingEnabled: true, // 开启原生文件写入
  fileLoggingMinLevel: LogLevel.info, // 仅 Info 及以上写文件
  logRetentionStrategy: LogRetentionStrategy.days,
  logRetentionCount: 7,
);

示例:只保留最近 3 个月:

PDLog.updateConfigure(
  logRetentionStrategy: LogRetentionStrategy.months,
  logRetentionCount: 3,
);

示例:只保留最近 1 年:

PDLog.updateConfigure(
  logRetentionStrategy: LogRetentionStrategy.years,
  logRetentionCount: 1,
);

说明:

  • updateConfigure 设置滚动策略后会自动执行一次清理(异步),不会阻塞调用;也可使用 PDLog.enforceRotation() 手动触发:
final deleted = await PDLog.enforceRotation();
  • Web 平台不支持文件写入,滚动策略对 Web 为 no-op;其他平台通过原生实现的文件枚举与删除接口执行清理,但滚动判定逻辑完全在 Dart 层实现,避免多平台重复代码。

  • 当前存储格式

    • 文件组织结构(自 0.5.0 起)
      • 根目录 :
        • iOS: .../Library/Application Support/pd_log/(应用沙盒内)
        • macOS: ~/Library/Application Support/pd_log/
        • Android: /data/data/<package>/files/pd_log/
        • Windows: %LOCALAPPDATA%\pd_log\(若未设置则回退到 %USERPROFILE%\AppData\Local\pd_log\
        • Linux: $XDG_DATA_HOME/pd_log/(如未设置则回退到 ~/.local/share/pd_log/
      • 年份目录 :按年份创建子目录(如 2024/2025/
      • 月份目录 :在年份目录下按月份创建子目录(如 01/12/
      • 日志文件 :按日命名,格式为 dd.log(如 19.log),最终路径示例:pd_log/2025/01/19.log
    • 文件内容格式
      • 每行日志包含:
      2024-12-19 14:30:25.123 [D](PDLog) 日志消息内容
      
      • 格式: 时间戳 级别(标签) 日志消息内容

查询示例(按日期/年份/月)

// 按日期检查是否存在某天的日志文件,存在则返回绝对路径,否则返回空字符串
final path = await PDLog.logFilePathIfExists(DateTime(2025, 1, 19));
if (path.isNotEmpty) {
  // 读取或处理该日志文件
}

// 按年份列出所有日志文件(例如:2025 年)
final filesOfYear = await PDLog.listLogFilesByYear(2025);

// 按年份与月份列出所有日志文件(例如:2025 年 01 月)
final filesOfYearMonth = await PDLog.listLogFilesByYearMonth(2025, 1);

示例项目

仓库内 example/ 目录提供了一个最小可运行示例,展示如何集成与使用 pd_log。你可以直接运行:

  • flutter run -d <your-device>

支持平台

  • Android / iOS / macOS / Windows / Linux / Web
  • Web 端使用 console 输出(不支持文件写入);其他平台支持原生侧缓冲与文件写入。

常见问题(FAQ)

  • 如何关闭控制台打印但保留文件日志?
    • 设置 useConsole: falsenativeFileLoggingEnabled: true
  • 是否会在 Release 模式打印控制台?
    • useConsole 仅在 kDebugMode 下生效,Release 默认不打印。
  • 开启 showCaller 有性能影响吗?
    • 有少量开销,因为需要解析调用栈,建议仅在调试环境开启。0.2.1 使用 stack_trace 以提升跨平台稳定性与准确性。
  • 日志路径结构是否变更?
    • 0.5.0 起,日志路径改为 /<year>/<month>/<day>.log(例如:pd_log/2025/01/19.log)。
    • 现有接口(listLogFiles 递归枚举、listYearFolders 一级目录)保持不变,兼容新的月份子目录。
    • 若存在历史 /<year>/<yyyy-MM-dd>.log 结构,可按需迁移或保留;枚举与删除接口仍可递归处理。

许可证

本项目基于 MIT 许可证开源,详见仓库根目录 LICENSE 文件。

Libraries

pd_log
pd_log 的核心 Dart API:统一日志输出、原生桥接与日志文件查询。
pd_log_method_channel
pd_log_platform_interface
pd_log_web