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/
)
- iOS:
- 年份目录 :按年份创建子目录(如
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: false
与nativeFileLoggingEnabled: 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