shell
#
# file: 20250406.log
# logger.info('Test logger.info...')
# logger.warn(new Map([['name', '这是一个 Map 对象']]))
#
┌────────────────────────────────────────────────────────────────────────────────
│ Info | 2025-04-06 14:58:59.810 (+00:00:25.276)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ Test logger.info...
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ #0 at print (library/src/main/ets/service/printer.ets:235:45)
│ #1 at print (library/src/main/ets/service/printer.ets:269:12)
│ #2 at log (library/src/main/ets/abstract/logger.ets:114:22)
└────────────────────────────────────────────────────────────────────────────────
┌────────────────────────────────────────────────────────────────────────────────
│ Warn | 2025-04-06 14:59:01.820 (+00:00:27.286)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ {
│ "__type__": "Map",
│ "__value__": {
│ "name": "这是一个 Map 对象"
│ }
│ }
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ #0 at print (library/src/main/ets/service/printer.ets:268:45)
│ #1 at print (library/src/main/ets/service/printer.ets:302:12)
│ #2 at log (library/src/main/ets/abstract/logger.ets:154:22)
└────────────────────────────────────────────────────────────────────────────────
前言
在 HarmonyOS 应用开发过程中,高效的日志系统
对开发调试和问题排查至关重要。传统的 hilog
原生接口虽然功能完备,但在实际开发中仍存在诸多不便:
- 复杂数据:需要手动序列化对象和集合类型
- 日志过滤:缺乏运行时动态调整日志级别的能力
- 本地缓存:没有内置的日志文件管理和轮转机制
- 日志上报:缺少开箱即用的日志上报云端的方案
之前在开发 Flutter App 时,使用过 Flutter logger
日志库,其优雅的设计给我留下了深刻印象。受此启发,我决定开发 HarmonyOS 类似的日志解决方案 (logger)
- 支持 多种数据类型,如基本数据类型、对象、Class、Map、Set 等支持 JSON 序列化数据
- 支持 自定义日志行为,如日志动态过滤、本地文件读写(定期自动清理)、云端日志上报等
- 支持 HarmonyOS Next API12+
- 支持 堆栈信息输出
准备
-
前往鸿蒙三方库中心仓,注册 ohpm 账号 (openharmony)
-
前往【个人中心 / 认证管理】,新增 OHPM 公钥
shell# ssh-keygen 创建公私密钥,需要注意的是 passphrase 不可省略!!! # -------------------------------------------------------------- ssh-keygen -m PEM -t RSA -b 4096 -f ~/.ssh_ohpm/id_rsa_publish Generating public/private RSA key pair. Enter passphrase (empty for no passphrase):
-
前往【个人中心】复制发布码,本地设备配置 publish_id
shell# your_publish_id: 你复制的发布码 # ---------------------------------------------- ohpm config set publish_id your_publish_id
日志库
-
梳理基本功能,定义抽象类 API
API 作用 详细描述 Filter 日志过滤 控制哪些日志需要被记录,支持日志级别过滤 (DEBUG/INFO/WARN/ERROR) 等 Output 日志输出流管理 定义日志最终输出位置和行为, 如控制台、本地文件、网络上报、多输出源组合 Printer 日志内容格式化 负责日志视觉呈现, 如文本格式化(颜色/缩进/边框)、结构化输出、堆栈跟踪 Logger 日志触发执行入口 提供开发者调用日志接口, 多级别日志方法 (debug、info、warn、error等) -
基于上述 抽象类 API,实现核心功能
API 继承 作用 详细描述 SafeFilter Filter
基础日志过滤 基于日志级别的基础过滤 (DEBUG、INFO、WARN、ERROR) SafeWriteFileOutput Output
文件系统日志输出 支持自动创建日志目录(按天)、日志文件轮转存储、异常恢复机制, 同时定义了 异步锁 AsyncMutex 优化极短时间内的同时写入和读取 SafeConsoleOutput Output
控制台日志输出 适配 DevEco Studio 控制台,支持颜色区分和高亮 SafeMultiOutput Output
多目标组合输出 适配多端输出源,支持输出权重配置 SafeSimplePrinter Printer
简约日志格式 单行文本输出,无额外装饰(无时间戳/无边框),适合高频调试日志 SafePrettyPrinter Printer
美观格式化输出 带边框的多行格式化,自动对齐键值对,支持显示堆栈跟踪记录,支持复杂对象树形展示 SafeHybridPrinter Printer
混合策略打印机 不同日志级别使用不同打印策略,支持自定义级别映射 SafeLogger Logger
开发者调用入口 提供开发者调用日志接口, 多级别日志方法 (debug、info、warn、error 等) -
预设了默认选项,以便开发者快速入手使用
typescript// 默认预设 import { SafeLogger } from 'logger' import { SafeFilter } from 'logger' import { SafeMultiOutput } from 'logger' import { SafeConsoleOutput } from 'logger' import { SafeWriteFileOutput } from 'logger' import { SafePrettyPrinter } from 'logger' import { SafeSimplePrinter } from 'logger' import { SafeHybridPrinter } from 'logger' export const logger = new SafeLogger({ printer: new SafeHybridPrinter(new SafePrettyPrinter(), { debug: new SafeSimplePrinter() }), output: new SafeMultiOutput([new SafeConsoleOutput(), new SafeWriteFileOutput()]), filter: new SafeFilter(), }) // 当然,也支持开发者自定义,例如: logger.reset({ printer: new SafeHybridPrinter(new SafePrettyPrinter({ lineLength: 120 }), { debug: new SafeSimplePrinter() }), output: new SafeMultiOutput([ new SafeWriteFileOutput({ storage: 'example/logger/cache', fileFormatter: 'harmony.[yyyyMMdd]' }), new SafeConsoleOutput() ]), })
typescript// 开发者使用示范 /** * logger 写入 */ logger.info('Test logger.info...') logger.warn(new Map([['name', '这是一个 Map 对象']])) /** * logger 读取文件 */ await logger.info('Test logger.info...') const string = await logger.readAsString() // 返回 { filename: 文件名; content: 文本内容; type: 类型; }
-
其他高级功能,云端日志上报示范
typescriptlet bytes = 0 const limit = 10 * 1024 * 1024; // 限制 10M 大小 const bufs = await logger.readAsArrayBuffers() const formData = new FormData() for (const buf of bufs) { if (bytes > limit) { break } formData.append('file', buf.buffer, { filename: buf.filename, type: buf.type }) bytes = bytes + buf.buffer.byteLength } axios.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } });
仓库
OpenHarmony logger
Github logger
欢迎给个 Star 👍