winston 日志模块
在使用 nodejs winston 模块中,加上相关的两个模块,事倍功半。
- express-winston
- winston-daily-rotate-file
express-winston
是 express-winston 的 winston 的增加版, 是作为 express 的中间件来打印日志,不仅有请求头信息,并且有响应时间。 作为中间件, 为什么会有响应时间呢? 因为 express-winston 改写了 express 的 res.end 办法, 是请求结束后再打的日志。
代码片段
express-winston 没有修改或者扩展 winston 的transport, 而 winston-daily-rotate-file 正是增强了 winston 的transport 办法
winston-daily-rotate-file
winston-daily-rotate-file 是 winston 扩展, 增加了 transport 的办法,使 winston 有滚动日志的能力。
结合使用
我们来一个需求: 如何让 express-winston 打印日志的时候,也打印出接口 /api 的请求参数和响应数据?
- 该日志中间件应该在调用链 api 后面, api/* 业务处理之前。 like: app.use('/api',apiRequestLogger,apiHandler)
- 要获取到响应数据, 就要在业务处理完后 send 出来后才能捕获到,express 所有的请求响应最后都是走 res.send 我们可以从这里入手捕获响应数据
代码如下
return new (winston.transports.DailyRotateFile)({
filename: path.join(process.env.LOGPATH,
${fileName}-%DATE%.log
),datePattern: 'YYYY-MM-DD-HH',// maxSize: '20m',maxFiles: '7d',timestamp: () => new Date().format('yyyy-MM-dd hh:mm:ss.S')})
}
export let pageRequestLogger = expressWinston.logger({
transports: [
DailyRotateFileTransport('page-request')
],Meta: true,// optional: control whether you want to log the Meta data about the request (default to true)
msg: 'HTTP {{req.method}} {{req.url}}',// optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
expressFormat: true,// Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
colorize: false,// Color the text and status code,using the Express/morgan color palette (text: gray,status: default green,3XX cyan,4XX yellow,5XX red).
ignoreRoute: function (req,res) {
// 只打印页面请求信息
let notPageRequest = false
let ignoreArr = ['/api','.js','.css','.png','.jpg','.gif']
ignoreArr.forEach(item => {
if (req.url.indexOf(item) > -1) notPageRequest = true
})
return notPageRequest
} // optional: allows to skip some log messages based on request and/or response
})
export let apiRequestLogger = (req,res,next) => {
let send = res.send
let content = ''
let query = req.query || {}
let body = req.body || {}
res.send = function () {
content = arguments[0]
send.apply(res,arguments)
}
expressWinston.logger({
transports: [
DailyRotateFileTransport('api-request')
],// optional: control whether you want to log the Meta data about the request (default to true)
msg () {
return HTTP ${req.method} ${req.url} query ${JSON.stringify(query)} body ${JSON.stringify(body)} resData ${content}
},colorize: true,res) {
if (req.headers.self) return true
return false
} // optional: allows to skip some log messages based on request and/or response
})(req,next)
}