参考:
Log4js配置详解
Node.js 之 log4js 完全讲解
log4js 是 Node.js 日志处理的模块,支持日志分级、日志分类、日志落盘。
简单例子
1 | const log4js = require('log4js'); |
运行控制台输出1
[2019-07-15T10:20:30.398] [INFO] default - test
调用 .getLogger() 可以获得 log4js 的 Logger 实例,这个实例的用法与 console 是一致的,可以调用.debug(也有 .info、.error 等方法)来输出日志。
这里的配置我们后文会一一介绍,接下让我们先熟悉几个 log4js 中的概念。
Level
这个理解起来不难,就是日志的分级。日志有了分级,log4js 才能更好地为我们展示日志(不同级别的日志在控制台中采用不同的颜色,比如 error 通常是红色的),在生产可以有选择的落盘日志,比如避免一些属于.debug才用的敏感信息被泄露出来。
log4js 的日志分为九个等级,各个级别的名字和权重如下:
1 | ALL: new Level(Number.MIN_VALUE, "ALL"), |
ALL OFF 这两个等级并不会直接在业务代码中使用。剩下的七个即分别对应 Logger 实例的七个方法,.trace .debug .info …。也就是说,你在调用这些方法的时候,就相当于为这些日志定了级。因此,之前的 [2016-08-21 00:01:24.852] [DEBUG] [default] - Time: 2016-08-20T16:01:24.852Z 中的 DEBUG 既是这条日志的级别。
类型
log4js 还有一个概念就是 category(类型),你可以设置一个 Logger 实例的类型,按照另外一个维度来区分日志:1
2
3
4const log4js = require('log4js');
const logger = log4js.getLogger('example');
logger.debug("Time:", new Date());
在通过 getLogger 获取 Logger 实例时,唯一可以传的一个参数就是 loggerCategory(如’example’),通过这个参数来指定 Logger 实例属于哪个类别。
我们修改一下之前的例子1
2
3
4
5
6
7
8
9
10
11
12
13const log4js = require('log4js');
log4js.configure({
appenders: {
out: { type: 'stdout' }
},
categories: {
default: { appenders: ['out'], level: 'info' }
}
});
const logger = log4js.getLogger('example');
logger.info("Time:", new Date());
运行后控制台输出:1
[2019-07-15T10:31:05.149] [INFO] example - Time: 2019-07-15T02:31:05.149Z
[default] 变成了 example
类别比级别更为灵活,为日志了提供了第二个区分的维度。
Appender
在 log4js 中,日志的出口问题(即日志输出到哪里)由 Appender 来解决。
默认 appender1
2
3
4
5
6// log4js.js
defaultConfig = {
appenders: [{
type: "console"
}]
}
在没有对 log4js 进行任何配置的时候,默认将日志都输出到了控制台。我们可以通过log4js.configure来设置我们想要的 appender,我们修改一下之前的配置。
1 | const log4js = require('log4js'); |
运行代码,log4js 在当前目录创建了一个名为default.log 文件,[2019-07-15T10:45:35.192] [INFO] custom-appender - Time: 2019-07-15T02:45:35.192Z输出到了该文件中。
Console 和 File 都是 log4js 提供的 appender,除此之外还有:
- DateFile:日志输出到文件,日志文件可以安特定的日期模式滚动,例如今天输出到default-2016-08-21.log,明天输出到 default-2016-08-22.log;
- SMTP:输出日志到邮件;
- Mailgun:通过 Mailgun API 输出日志到 Mailgun;
- levelFilter 可以通过 level 过滤;
等等其他一些 appender,到这里可以看到全部的列表。
过滤级别和类别
我们可以调整 appender 的配置,对日志的级别和类别进行过滤:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24const log4js = require('log4js');
log4js.addLayout('json', function(config) {
return function(logEvent) {
return JSON.stringify(logEvent);
}
});
log4js.configure({
appenders: {
consoleJson: { type: 'console', layout: { type: 'json' } },
console: { type: 'console' }
},
categories: {
default: { appenders: ['console'], level: 'info' },
all: { appenders: ['consoleJson', 'console'], level: 'info' }
}
});
const logger1 = log4js.getLogger();
const logger2 = log4js.getLogger('all');
logger1.debug("Time:", new Date());
logger2.info("Time:", new Date());
log4js.shutdown(() => {});
运行结果:1
2{"startTime":"2019-07-15T13:53:28.174Z","categoryName":"all","data":["Time:","2019-07-15T13:53:28.174Z"],"level":{"level":20000,"levelStr":"INFO","colour":"green"},"context":{},"pid":12642}
[2019-07-15T21:53:28.174] [INFO] all - Time: 2019-07-15T13:53:28.174Z
- 使用 level 来对日志的级别进行过滤,所有权重大于或者等于info的日志将会输出。这也是之前提到的日志级别权重的意义;
- 通过 category 来选择要输出日志的类别,该配置也接受一个数组,例如 [‘consoleJson’, ‘console’],这样配置两个类别的日志都将输出到文件中。
Layout
Layout 是 log4js 提供的高级功能,通过 layout 我们可以自定义每一条输出日志的格式。log4js 内置了四中类型的格式:
- messagePassThrough:仅仅输出日志的内容;
- basic:在日志的内容前面会加上时间、日志的级别和类别,通常日志的默认 layout;
- colored/coloured:在 basic 的基础上给日志加上颜色,appender Console 默认使用的就是这个 layout;
- pattern:这是一种特殊类型,可以通过它来定义任何你想要的格式。
一个 pattern 的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14const log4js = require('log4js');
log4js.configure({
appenders: {
console: { type: 'console', layout: { type: 'pattern', pattern: '[%r] [%[%5.5p%]] - %m%n' } },
},
categories: {
default: { appenders: ['console'], level: 'info' },
}
});
const logger = log4js.getLogger();
logger.info("Time:", new Date());
log4js.shutdown(() => {});
%r %p $m $n 是 log4js 内置的包含说明符,可以借此来输出一些 meta 的信息,更多细节,可以参考 log4js 的文档。
这里,我们总结一下Logger、Appender 和 Layout 的定位。
- Logger 输出的日志内容
- Appender 日志输出到哪
- Layout 如何输出日志
实战
一个应用日志配置的例子
1 | const log4js = require('log4js'); |
看看我们做了哪些事情:
- 配置了两个appender,一个为console,另一个为file,file输出到一个滚动的文件中;
- 使用log4js.getLogger(‘file’) 获取一个类别为 file 的 Logger 实例,传递给log4js.connectLogger 中间件,这个中间件收集访问信息,通过这个实例打出。