Nodejs日志库log4js快速入门
在NodeJs项目中,log4js一般会作为日志库的首选,本篇来快速入门一下log4js的一些配置和使用规则。
本文只介绍常用内容,具体细节请查看log4js官方文档
本文基于
log4js@6.9.x演示过程中使用
esmodule规范,在package.json中指定type为module即可在nodejs中使用esmodule规范。
安装log4js输出第一条日志
直接通过npm进行安装即可:
1 | npm install log4js |
我们新建index.js并引入log4js测试一下:
1 | // index.js |
此时我们执行node index.js可以发现控制台并没有任何输出,刚开始就跳坑了吗?
查看官方文档我们可以知道必须要对log4js进行配置,先不关注配置项的规则,我们先写几条试一下:
1 | // index.js |
此时再通过nodejs运行这个文件就能在控制台看到输出我们的第一条日志了:
log4js的一些概念
前边我们看到了一些如追加器、类别、日志级别等概念,这一节就先说一下这些概念,不然后边容易看不懂。
追加器appenders
追加器负责日志事件的输出。他们可以将事件写入文件、发送电子邮件、将它们存储在数据库中或任何内容。大多数追加程序使用布局将事件序列化为字符串以进行输出。
追加器主要是自定义命名追加器 对 默认追加器对象的映射。是一个对象。
说人话就是我们自己可以定义一个名字作为追加器的key,其value是一个对象,这个对象指向一个log4js定义的追加器。所以这个value必须有一个type属性,type是一个字符串描述使用哪一种追加器,是否需要其他字段取决于type使用哪种追加器。
比如
1 | appenders: { |
这里没想到怎么去翻译,所以自定义的
key也称为追加器名称了。这个自定义追加器名称 就是 对
log4js某个追加器的自定义配置
类别categories
用于对日志事件进行分组的标签。类别的配置方式与追加器是类似的,也是我们自定义一个类别名称,然后指定这个类别使用哪些追加器以及日志级别等。而且必须要定义一个名为default的类别。类别配置接收三个字段:
- appenders: 要使用的追加器,是一个字符串数组,这里配置的就是我们自定义的追加器名称。
- level: 日志级别,很重要,后边会说。这里是对于logger的最低级别限制,如果用了该category的logger以低于该级别输出日志是不会输出的
- enableCallStack: 可选字段,是一个布尔值,默认为false。
日志级别level
日志级别是日志事件(调试、信息等)的严重性或优先级。追加者是否会看到事件取决于类别的级别。如果此值小于或等于事件的级别,则会将其发送到类别的追加器。
将日志分为不同等级对日志进行分类,优先级由低到高为:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < MARK < OFF。
注意,off是用来关闭日志,而不是作为日志级别
也就是说我们永远不会用
logger.off()来输出日志
日志对象logger
这是你的代码与log4js的主界面。记录器实例可能具有在创建实例时定义的可选类别。
我们通过log4js.getLogger()得到logger对象
getLogger([category])接收一个可选参数category,类型为字符串。如果不传递就会使用default,这就是我们前边说的必须要定义一个default类别的原因。
logger对象上有一个常用属性level,我们可以对其进行修改,后边会做演示。
日志事件
比如logger.info, logger.error, logger.debug等都是触发日志事件
logger.info, logger.error等事件是表示以指定日志级别输出日志,当然如果日志级别低于category设置的级别是被忽略的。
布局layout
用于将日志事件转换为字符串表示的函数。有些抽象,后边具体说吧。
configure配置
使用log4js的第一步就是要配置configure。
配置项
先过一下configure的所有配置项吧:
levels: 可选参数,定义日志级别。appenders: 追加器categories: 类别pm2: 可选参数,布尔值,如果使用pm2运行应用需要设置为truepm2InstanceVar: 可选参数,如果未更改pm2的默认配置,一般来说不需要设置disableClustering: 可选参数,布尔值,关于集群配置的,不太懂就不说了。
因为关于追加器、类别等还是有很多可自定义配置的,要放到后边来说,所以我们接下来结合前边说的内容做一些简单的配置演示。
多类别应用
我们运用前边的知识,创建多个appender和category来测试
1 | import log4js from 'log4js' |
运行该文件,可以看到控制台输出:
可以看到,使用
category为all的logger输出了2条日志
日志级别控制
1 | import log4js from 'log4js' |
执行可以看到控制台输出结果:
由此可见,低于指定
level的日志输出会被忽略
追加器appenders
在前边,我们只用到了console和stdout这两个appender,也是最简单的两个,在项目中这肯定是不够的,所以这里我们介绍一些常用的appender。
console
console使用NodeJs的console.log来输出日志到控制台,比较简单,就不再多做演示了。
可配置项:
type:consolelayout: 布局放到后边说
注意!
将大量日志输出到控制台可能会导致内存占用上升,尽量不要在生产环境中启用。
可以使用
stdout作为appender来代码console以减少内存占用
console总是使用console.log,即便logger.error()输出日志也并不会使用console.error。
stdout
stdout是log4js的默认appender,将所有日志事件写入标准输出流。
可配置项:
type:stdoutlayout: 布局放到后边说
stderr
与stdout有些相似,不过是将所有日志事件写入标准错误流
可配置项:
type:stderrlayout: 布局放到后边说
logLevelFilter
这个appender很有意思,我们前边是在category设置的level,其实在appender中也可以进行一些限制,就是用到logLevelFilter
可配置项:
type:logLevelFilterappender: 真正要用的追加器,比如stdoutlevel: 允许通过追加器的最低日志级别限制maxLevel: 可选参数,允许通过追加器的最大日志级别限制,默认为fatal
如果事件的级别大于或等于
level且小于或等于maxLevel,则它将被发送到追加器。
代码如下:
1 | import log4js from 'log4js' |
执行该文件的结果如下:
总结:
如果日志事件的级别 低于 类别定义的级别, 该事件会被忽略
如果日志事件的级别 不低于 类别定义的级别,那么该事件会生效,但是如果该类别中应用到了logLevelFilter追加器,需要不低于该追加器定义的级别才会应用该追加器,其他追加器不受影响
file
将日志写入到文件是基础的需求,我们来看一下file appender。
将日志事件写入文件。它支持可选的最大文件大小,并将保留可配置数量的备份。
可配置项:
type:filefilename: 要写入日志的文件的路径maxLogSize: 可选参数,日志的最大大小(以字节为单位)。如果指定为0或不指定,则不会发生日志滚动backups: 可选参数,默认5,日志滚动期间要保留的旧日志文件数layout: 布局放到后边说
在应用程序终止时调用
log4js.shutdown,以确保任何剩余的异步写入都已完成
不限制日志大小示例
1 | import log4js from 'log4js' |
此时多次执行这个文件,会发现在同级目录创建了一个文件app-log.log,内容如下:
限制日志文件大小
代码如下:
1 | import log4js from 'log4js' |
执行一次代码,可以发现app-log.log文件已经被创建了,大小为7kb,写入内容如下:
我们在次执行代码,可以发现创建了一个新的文件app-log.log.1存储旧的日志,而超过大小限制无法写入的内容写入到了app-log.log中。
不难发现,在写入到139行之后超过了10kb的限制,所以将这些内容备份到
app-log.log.1中,将未写入到61行日志写入到了app-log.log中
注意:
由于我们限制了备份到日志数量,所以当达到最大限制后,新的日志会覆盖旧的日志。
file appender还可以配置compress为true,如果这样配置的话会将备份文件进行gzip压缩,也就是缓存文件会被压缩为app-log.log.1.gz,其他的行为是一致的就不演示了。
fileSync
用法与file基本是一致的,就不演示了,主要区别如下:
fileSync写入文件是同步的,而file是异步的fileSync不支持配置compress将日志文件进行gzip压缩
还有
multiFile可以动态写入多个文件,有兴趣可以自行学习一下,这里不说了。
dataFile
更常用的追加器来了,dataFile也是一个文件追加器,它根据可配置的时间(而不是文件大小)滚动日志文件。
基础配置项:
type:dataFilefilename: 要写入的文件路径pattern: 可选字符串,默认为yyyy-MM-dd,用来确定怎么分割滚动日志
先根据这几个基础的字段来看一下用法,由于默认是以天分割,不方便演示,所以我这边设置pattern为分钟。
代码示例:
1 | import log4js from 'log4js' |
执行代码可发现生成了日志文件
过了一分钟,我们再次执行代码观察日志文件:
可以得出我们写入日志时,会生成
app-log.log文件。一分钟后的再次写入发生时,会将app-log.log重命名为app-log.log.yyyy-MM-dd-hh-mm然后创建一个新的app-log.log文件写入内容。文件命名与时间分割都由
pattern决定。默认是以天分割。
还有一些其他的配置项,比较容易看懂,就不做代码示例了:
compress: 是否使用gzip压缩,默认为falsekeepFileExt: 布尔值,默认为false, 如果为true,则备份的日志文件将被命名为app-log.yyyy-MM-dd.log,而不是app-log.log.yyyy-MM-ddfileNameSep: 备份文件命名的切割符,默认是.numBackups: 保存旧文件的数量,默认是1
file和dateFile等文件写入的appender,都可以配置mode、 encodeing、 flags等,一般情况下默认值即可。默认值是0o600 、 utf-8、'a'。也就是读写权限,utf8编码,追加模式
关于appenders的内容就到这里了,还有更多tcp等appender去文档查看吧。
类别categories
类别是日志事件的组,至少要定义一个类别。
类别可以说的不多,前边的示例中演示过了,只说一个比较特别的功能类别继承
以官方的代码示例:
1 | import log4js from 'log4js' |
可以发现,
loggerAB使用的类别为catA.catB,即便catA的级别为error,loggerAB.trace同样可以同时应用两种appender
布局layout
前边关于布局layout的内容,我们都省略掉了,其实是有原因的,log4js给各种appender默认添加了合适的布局,所以一般来说我们是不需要额外定义布局的。
布局的配置方式根appender是比较像的,log4js内置了几种layout,根据type指定layout,根据不同layout可能还有不同的配置项。
做一个简单的演示:
1 | import log4js from 'log4js' |
输出内容:
可以发现,basic布局是没有颜色的。输出内容是时间戳、级别、类别,后跟格式化的日志事件数据。而我们默认的布局是有颜色的,用到的是colored
由于我们一般不需要对布局进行修改,所以这里仅仅列一下log4js的内置布局:
basiccolored或colouredmessagePassThroughdummypattern
可以自定义布局,如果有这个需求可以查看文档学习
Nodejs日志库log4js快速入门
https://zhaolei-hu.github.io/2023/04/19/Nodejs日志库log4js快速入门/