Skip to content

Ericple/log4a

Repository files navigation

Log4a

轻量、易集成、易使用,有时甚至可以不需写代码的HarmonyOS log系统,灵感来自log4j。

Log4a文档

本README受篇幅限制,新特性将不再在此处介绍,有关Log4a功能详情,请查阅文档。 文档网站支持在线体验并运行Log4a Github站文档版本更新,国内站版本较老,建议前往GitHub站阅读文档

特点

  • 支持TS工程引入
  • 提供日志装饰器,无需自己配置log4a,自动跟踪函数调用情况
  • 使用fatal、error输出时,支持打印调用堆栈
  • 支持日志输出到文件,利用多线程特性,提高日志输出到文件的性能
  • 格式化日志输出,借鉴log4j,贴合使用习惯
  • Logger统一管理,降低内存占用
  • 支持格式化打印对象
  • 通过设置日志级别,提供日志过滤服务
  • 支持日志加密写出到文件
  • 支持配置日志文件最大容量,溢出后新建日志文件
  • 支持配置日志文件备份数量,溢出后滚动删除
  • 支持自定义日志Layout
  • 支持使用过程中重新配置Logger及Appender

由于ohpm中心仓库审核需要时间,若您遇到恶性bug但中心仓库未提供更新, 请先移步log4a代码仓库检查是否存在新版本, 若没有,您可以新建issue ,或向我发送邮件,我将尽快修复。

安装

  • 使用 ohpm 以安装 @pie/log4a
ohpm install @pie/log4a

对于其他安装方式, 请参考 这篇文章.

使用

通用流程

  • 获取logger

使用LogManager.getLogger(context)获取当前对象的可用Logger。该方法传入this即可。

import { LogManager, Logger } from '@pie/log4a';

class LogTestClass {
  private logger: Logger = LogManager.getLogger(this);
  // ... Other code
}
  • 使用logger

获取logger后,即可开始打印日志:

import { LogManager, Logger } from '@pie/log4a';

class LogTestClass {
  private logger: Logger = LogManager.getLogger(this);

  add(a: number, b: number) {
    this.logger.info('calculating {} + {}', a, b);
    return a + b;
  }
}

const adder = new LogTestClass;
adder.add(1, 2);

上面这段代码在执行之后,会打印出这样一条日志

[INFO ] 2024-04-19  23:32:54.746  [LogTestClass:1]  calculating 1 + 2

可以看到,log4a打印出的日志中包含了以下信息:

  • 日志级别
  • 日志时间
  • 日志来源
  • 日志内容

日志来源

当logger属于class或struct时:

对于非静态logger,日志来源为class或struct的名称

对于静态logger,日志来源为Function

import { LogManager, Logger } from '@pie/log4a';
class StaticLogger {
  private static logger: Logger = LogManager.getLogger(this);
  static hello() {
    StaticLogger.logger.info("Hello from static logger");
  }
}

这段代码将会打印:

[INFO ] 2024-04-19  23:32:54.746  [Function:1]  Hello from static logger
  • 带标记的日志

对于一些匿名输出,可以通过添加标记的方式便于在日志中进行搜索,例如:

LogManager.anonymous().withMarker(MarkerManager.getMarker("我是一个Marker")).info('这是带Marker的日志');

追踪器

log4a设计了追踪器,它可以帮你跟踪函数运行参数、函数运行结果、模板字符串的构造。

可用的追踪器:

@TraceEntry

  • @TraceEntry:用于跟踪函数运行参数,示例如下:
import { TraceEntry } from '@pie/log4a';

class TestClass {
  @TraceEntry
  add(a: number, b: number): number {
    return a + b;
  }
}

const t = new TestClass;
t.add(1, 2);

虽然没有写任何的log代码,但这段代码在运行后仍然会出现如下log:

[TRACE]	2024-04-20 00:19:43.24	[TestClass:1]	Method: [add] called with arguments [1,2]

这意味着,使用@TraceEntry装饰的函数将会被追踪,每当它被调用时,log4a都会打印一条日志,该日志包含该函数名称及本次调用传入的参数。

@TraceExit

  • @TraceExit:用于跟踪函数运行结果,示例如下:
import { TraceExit } from '@pie/log4a';

class TestClass {
  @TraceExit
  add(a: number, b: number): number {
    return a + b;
  }
}

const t = new TestClass;
t.add(1, 2);

虽然没有写任何的log代码,但这段代码在运行后仍然会出现如下log:

[TRACE]	2024-04-20 00:19:43.24	[TestClass:1]	Method: [add] exited with result: 3

这意味着,使用@TraceExit装饰的函数将会被追踪,每当它被调用时,log4a都会打印一条日志,该日志包含该函数名称及本次调用返回的结果。

TracedStr

  • TracedStr:用于跟踪字符串模板的构建过程,示例如下:
import { TracedStr } from '@pie/log4a';

class TestClass {
  param1: string = 'param1';
  param2: string = 'param2';
  str: string = TracedStr`build with ${this.param1} and ${this.param2}`;
}

const t = new TestClass;

虽然没有写任何的log代码,但这段代码在运行后仍然会出现如下log:

[INFO ]	2024-04-20 00:27:51.989	[Anonymous:1]	built with format: ["build with "," and ",""] and args: ["param1","param2"] (Anonymous)

注意,TracedStr是标签而不是装饰器,因此不需要@前导。

MarkedTracedStr

  • MarkedTracedStr:为了方便使用者追踪特定的模板字符串构建,使用此标签并传入一个字符串作为标记
import { MarkedTracedStr } from '@pie/log4a';

class TestClass {
  param1: string = 'param1';
  param2: string = 'param2';
  str: string = MarkedTracedStr("StrBuilder")`build with ${this.param1} and ${this.param2}`;
}

const t = new TestClass;

虽然没有写任何的log代码,但这段代码在运行后仍然会出现如下log:

[INFO ]	2024-04-20 00:33:31.793	[Anonymous:2]	built with format: ["build with "," and ",""] and args: ["param1","param2"] (StrBuilder)

注意,MarkedTracedStr是函数而不是标签,需要传入一个参数。

Appender

Appender为Logger提供日志输出能力,分为两种类型:FileAppenderConsoleAppender。 新建Logger时,将自动提供一个ConsoleAppender。Appender无法直接被创建,只能通过调用Logger实例下的addFileAppenderaddConsoleAppender来创建并绑定到该Logger.

ConsoleAppender

ConsoleAppender提供向控制台输出日志的能力,每个Logger在创建时,就会带有一个ConsoleAppender,无需手动添加。 一个Logger最多只能拥有一个ConsoleAppender,当您向Logger添加ConsoleAppender时,若已存在,则该appender不会被添加至Logger。

  • 添加一个ConsoleAppender
// this.logger是一个Logger的实例
this.logger.addConsoleAppender(Level.INFO);
  • 移除ConsoleAppender
this.logger.removeTypedAppender(AppenderTypeEnum.CONSOLE);
  • 获取当前Session的历史日志
this.logger.getHistoryOfAppender(AppenderTypeEnum.CONSOLE);

FileAppender

FileAppender提供向文件输出日志的能力。 一个Logger可以有多个FileAppender,如果有多个FileAppender指向同一个文件,则这些FileAppender将会共用一个文件对象。

添加一个FileAppender
this.logger.addFileAppender('/file/log.log', 'mainAppender', Level.INFO);
删除一个FileAppender
this.logger.removeNamedAppender('mainAppender');
获取当前Session的历史日志(从本次开启应用开始)
const history = this.logger.getHistoryOfAppender('mainAppender');
获取所有历史日志(从首次安装并启动应用开始,每次应用销毁后更新,下次继续累计)
const history = this.logger.getAllHistoryOfAppender('mainAppender');
开启多线程支持
this.logger.addFileAppender('/file/log.log', 'mainAppender', Level.INFO, {
  useWorker: true
});
配置最大日志备份文件数量
this.logger.addFileAppender('/file/log.log', 'mainAppender', Level.INFO, {
  maxCacheCount: 10
});
配置最大日志容量
this.logger.addFileAppender('/file/log.log', 'mainAppender', Level.INFO, {
  maxFileSize: 10 // 最大10KB
});

日志级别

为了帮助使用者更容易地从日志中提取有用的信息,log4a引入了日志级别的概念。 Logger和Appender都可以附带日志级别,log4a对Logger的日志等级的处理优先于对appender的日志等级的处理,举例如下:

this.logger.setLevel(Level.ERROR);
this.logger.addFileAppender("/path/to/log.log", "mainFileAppender", Level.INFO);

在这个例子中,由于添加的FileAppender日志级别为INFO,高于Logger的日志级别ERROR,此时WARN级别的日志无法送达Appender。

(日志等级排序为:OFF<FATAL<ERROR<WARN<INFO<DEBUG<TRACE<ALL)

退出应用时的处理

在退出应用时,使用者应当在Ability的onDestroy生命周期中调用LogManager.terminate()来销毁Logger及Appender实例。

约束与限制

在下述版本验证通过:

  • DevEco Studio NEXT Developer Preview 2 (4.1.3.700), SDK: API11 (4.1.0(11))
  • DevEco Studio NEXT Beta1 (5.0.3.800), SDK: API12 (5.0.0(12))

本库理论上支持所有API版本,对于API10以下的项目,可自行克隆编译使用

贡献代码

开源协议

本项目使用Apache License 2.0

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors