安装与了解
npm install log4js --save
目前的版本是:6.6.1
在终端打印消息:
import log4js from 'log4js'
const logger = log4js.getLogger()
logger.level = 'all'
logger.debug('some debug messages')
终端效果:
[2022-09-08T15:25:23.776] [DEBUG] default - some debug messages
log4的日志默认由:时间 级别 类型 - 日志内容 组成
这里有了第一个概念,级别,log4可配置的级别一共有九个,这里找了一个参考图:
image.png
除了
all、off 外,其他七个级别从低到高如上图所示,log4只会输出同级别或者高级别的日志,效果如下:
const logger = log4js.getLogger()
logger.level = 'error'
logger.debug('some debug messages')
此时想去输出 debug 日志,但是设置的级别是error,log4不会输出比设置低级的日志。
第二个概念是类型,log4可以对我们的日志进行分类,回到上面的代码:
const logger = log4js.getLogger()
logger.level = 'all'
logger.debug('some debug messages')
输出:
[2022-09-08T15:25:23.776] [DEBUG] default - some debug messages
此时输出的类型的 default
可以在 getLogger 传入类型名称,使打印出来的日志带上类型:
const logger = log4js.getLogger('超人鸭')
logger.level = 'all'
logger.debug('some debug messages')
输出:
[2022-09-08T15:39:48.632] [DEBUG] 超人鸭 - some debug messages
这个类型在log4中叫 Categories,可以配置,详细配置下面讲。
上面只是log4的最简单使用,跟console.log没啥区别,但记录日志是需要记录到文件里面的,而且需要配置文件内容的格式,让我们更好的定位问题。
配置
log4的配置方式如下:
log4js.configure({
appenders: {},
categories: {}
})
通过log4js.configure方法传入一个配置对象进行配置,配置对象里面必须传入 appenders、categories。
在进行配置之前,先简单介绍一个log4三个最重要的对象之间的关系,以便更好的理解,三个对象为:appenders、categories、logger。(当然这都是我自己的理解,如有错误或者更好的解释欢迎指教,😊)
首先是 appenders,它的作用为定义日志输出到哪里:控制台、文件等,定义文件的格式:是普通文件还是以日期创建的文件,定义文件内容的格式:如何换行、包不包含调用栈、甚至可以通过函数插入内容等。
然后是 categories,它的作用是定义日志的类型,在输出的日志中显示。一个 categories 需要包含一个或多个 appenders,也就是定义某一种类型的时候,需要从定义好 appenders 中选择好这类日志该如何输出;同时定义类型的时候也需要定义好这类日志的级别。在配置的时候,必须配置一个 default 类型的配置。
最后是 logger ,它就是通过log4js.getLogger()返回的日志打印器,我们通过它来输出各个级别日志,通过传入配置的 categories 名称,来设置输出日志的类型,如果没有传入名称或者传入一个没有配置的类型名称,就会使用 default 类型的配置。
所以三者的关系总结就是:通过 logger 去输出,定义 logger 时传入配置好的 categories , 而每一个categories 又包含定义好的 appenders, 它规定日志如何去输出。
下面通过一个官方的例子来了解一下:
import log4js from 'log4js'
log4js.configure({
appenders: {
out: { type: 'console' },
app: { type: 'file', filename: 'application.log' }
},
categories: {
default: { appenders: ['out'], level: 'debug' },
test: { appenders: ['out', 'app'], level: 'debug' }
}
})
const logger = log4js.getLogger('test')
logger.level = 'debug'
logger.debug('some debug messages')
此时控制台输出:
[2022-09-08T16:23:18.464] [DEBUG] test - some debug messages
同时在项目的根目录自动生成一个 application.log 文件:
image.png
上面的
appenders 配置有非常多,需要先配置好 type,也就是日志输出的类型,有:console直接输出到终端、file 普通文件、dateFile 日期文件等等。
而每一种 type的其他配置又有所不同,下面我会简单讲我自己真正项目中的配置,有缘看到这篇文章的人可以作为参考。而 appenders 的其他详细配置就通过官方文档了解吧🌹。
参考配置
在真正项目需要去定位问题时,通过日期去查看文件会比较直接,所以 appenders 配置的 type 我选择的是 dateFile,其他配置都是基于这个 type。下面是我完整的配置:
import log4js from 'log4js'
log4js.configure({
appenders: {
console: {
type: 'console',
layout: { type: 'coloured' }
},
reqLog: {
type: 'dateFile',
filename: './logs/req/req',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log',
numBackups: 10
},
resLog: {
type: 'dateFile',
filename: './logs/res/res',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log',
numBackups: 10
},
infoLog: {
type: 'dateFile',
filename: './logs/info/info',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log',
numBackups: 10,
layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %m %n%s' }
},
warnLog: {
type: 'dateFile',
filename: './logs/warn/warn',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log',
numBackups: 10,
layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %m %n%s' }
},
errLog: {
type: 'dateFile',
filename: './logs/err/err',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log',
numBackups: 10,
layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %m %n%s' }
}
},
categories: {
default: {
appenders: ['infoLog', 'console'],
level: 'all',
enableCallStack: true
},
req: {
appenders: ['reqLog'],
level: 'info'
},
res: {
appenders: ['resLog'],
level: 'info'
},
info: {
appenders: ['infoLog', 'console'],
level: 'info',
enableCallStack: true
},
warn: {
appenders: ['warnLog', 'console'],
level: 'warn',
enableCallStack: true
},
err: {
appenders: ['errLog', 'console'],
level: 'error',
enableCallStack: true
}
},
pm2: true
})
下面对一些配置进行解释:
appenders 中的 layout ,通过它就可以自定义日志内容,其中 layout: { type: 'coloured' } 代表输出有颜色的日志,适合在终端中查看(现在的版本不配置layout好像也有颜色区别)。
layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %m %n%s' }代表通过占位关键词进行自定义格式定义,其中的 %s 代表输出调用栈,通常在错误日志中,我们需要知道是哪里打出来的日志,哪个文件哪个函数哪一行。如果需要输出 %s,在 categories 配置中就需要添加 enableCallStack: true 的配置。%m 代表日志内容, %n 代表换行。
配置中的 appenders 类型为 dateFile 的这几个配置:
filename: './logs/req/req.log',
alwaysIncludePattern: true,
pattern: 'yyyy-MM-dd.log
就都是配置文件名的格式,生成的文件名格式为:req.log.yyyy-MM-dd.log
配置中的 numBackups: 10 代表保留10天的日志文件,防止无限生成浪费磁盘空间。
然后是 categories ,类型的配置就比较简单,定义好每一种类型包含的 appenders 与 等级就行,对于部分日志,同时包含了文件记录与终端输出,方便开发时也可以即时查看,不需要再 console.log。categories 必须包含一个 default 配置。
最后一个是 pm2 ,对于使用 pm2 进行线上部署的项目,就需要使用,同时还要安装 pm2 的插件,下面是官方的说明:
pm2(boolean) (optional) - set this to true if you’re running your app using pm2, otherwise logs will not work (you’ll also need to install pm2-intercom as pm2 module:pm2 install pm2-intercom)
如果更改 pm2 的多进程注入的环境变量名称,就需要再配置 pm2InstanceVar ,这里详细就看官方文档了。
上面就是我真实项目中使用的配置,之后通过 log4js.getLogger() 得到 logger 方法,进行日志记录。上面我的 categories 配置基本是以类似等级来区别,通常都是不同等级的日志输出到不同的文件,所以 logger 方法输出的等级就是 categories 配置的等级且不会变,对此,可以定义好各个类型的输出方法,供外部调用,在与配置的同一个文件里面:
export function reqLog(content: any): void {
const logger = log4js.getLogger('req')
logger.info(content)
}
export function resLog(content: any): void {
const logger = log4js.getLogger('res')
logger.info(content)
}
export function infoLog(content: any): void {
const logger = log4js.getLogger('info')
logger.info(content)
}
export function warnLog(content: any): void {
const logger = log4js.getLogger('warn')
logger.warn(content)
}
export function errLog(content: any): void {
const logger = log4js.getLogger('err')
logger.error(content)
}
下面简单的示例,记录接口的请求与返回,使用koa的中间件,在koa的入口文件:
import { reqLog, resLog } from './utils/log4'
app.use(async (ctx, next) => {
reqLog(ctx.request)
await next()
resLog(ctx.response)
})
当引入log4配置文件后,会自动在项目根目录生成 appenders 定义日志文件:
image.png
下面随便调用一个接口,看看文件内容,req、res都没有使用
layout 定义:req请求文件:
image.png
res响应文件:
image.png
node中打印对象
先来看看一个现象:
const obj = {
1: {
2: {
3: {
4: {
5: {
6: {}
}
}
}
}
}
}
console.log(obj)
此时终端的输出:
image.png
可以看到打印到第三层往后,就会缩成
[Object] ,这时候可不像浏览器一样可以点展开。
这时候我们用log4去记录这个对象,看会得到什么:
reqLog(obj)
回到刚刚的文件:
image.png
可以看到输出的文件效果与
console.log 在终端的效果一样,它内部进行的处理与node处理是一样的,所以我们在输出日志之前需要对内容进行处理,使对象不会折叠,这里需要借助到 node 的 util 模块中的 inspect 方法。使用如下:
import util from 'util'
const obj = {
1: {
2: {
3: {
4: {
5: {
6: {}
}
}
}
}
}
}
console.log(
util.inspect(obj, {
showHidden: false,
depth: null,
colors: false
})
)
效果:
image.png
深层对象记录的问题解决,修改一下log4导出的方法:
function inspectContent(content: any) {
return util.inspect(content, {
showHidden: false,
depth: null,
colors: false
})
}
export function reqLog(content: any): void {
const logger = log4js.getLogger('req')
logger.info(inspectContent(content))
}
export function resLog(content: any): void {
const logger = log4js.getLogger('res')
logger.info(inspectContent(content))
}
export function infoLog(content: any): void {
const logger = log4js.getLogger('info')
logger.info(inspectContent(content))
}
export function warnLog(content: any): void {
const logger = log4js.getLogger('warn')
logger.warn(inspectContent(content))
}
export function errLog(content: any): void {
const logger = log4js.getLogger('err')
logger.error(inspectContent(content))
}
至此,一套可以供真实项目记录日志的log4配置就配置好了,如果你有更好的见解与用法,欢迎指教。











网友评论