我在编写基于express的web框架的时候由于需要打印大量与express关系不大的日志,为了统一没有使用morgan而是采用了log4js。同时随之而来了许多问题,其中最重要的问题便是让log4js打印express的日志。
强烈建议阅读官方readme
我看到的网上的教程大部分的代码都无法直接运行而且都没讲解清楚,随后我发现log4js的官方已经写出了log4js和express的配合方法,位于log4js-node/connect-logger.md中。在以下文章中我会翻译此页面并加上部分注释。
Connect / Express Logger
connect/express logger由danbell添加至log4js. 此方式允许connect/express使用log4js进行日志记录. 以下是 示例example-connect-logger.js
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var log4js = require('log4js'); var express = require('express');
log4js.configure({ appenders: { console: { type: 'console' }, file: { type: 'file', filename: 'cheese.log' } }, categories: { cheese: { appenders: ['file'], level: 'info' }, default: { appenders: ['console'], level: 'info' } } });
var logger = log4js.getLogger('cheese'); var app = express(); app.use(log4js.connectLogger(logger, { level: 'info' })); app.get('/', function(req,res) { res.send('hello world'); }); app.listen(5000);
|
log4js.connectLogger支持传递部分选项为以下的内容
- 日志等级(level)
- 日志格式化(format)字符串或是函数(和connect/express logger相同)
- nolog 表达式(不进行日志记录) (字符串,正则表达式或数组表示)
- 响应码过滤
例如:
1
| app.use(log4js.connectLogger(logger, { level: log4js.levels.INFO, format: ':method :url' }));
|
或者:
1 2 3 4 5
| app.use(log4js.connectLogger(logger, { level: 'auto', format: (req, res, format) => format(`:remote-addr - ${req.id} - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"`) }));
|
当你进行post请求时,你或许会想要记录请求主体(body)参数,比如JSON,此时日志格式化函数时非常有用的。请使用日志格式化函数来替代 “tokens” 属性来使用express的请求或者响应。
1 2 3 4
| app.use(log4js.connectLogger(logger, { level: 'info', format: (req, res, format) => format(`:remote-addr :method :url ${JSON.stringify(req.body)}`) }));
|
向connect-logger添加取决于http响应码的自动日志等级(level)检测功能在express 3.x 和4.x中可用
- 响应码 3xx, level = WARN
- 响应码 4xx & 5xx, level = ERROR
- 其他, level = INFO
1
| app.use(log4js.connectLogger(logger, { level: 'auto' }));
|
根据状态码修改日志等级可以通过状态码规则进行修改
1 2 3 4
| app.use(log4js.connectLogger(logger, { level: 'auto', statusRules: [ { from: 200, to: 299, level: 'debug' }, { codes: [303, 304], level: 'info' } ]}));
|
log4js.connectLogger同样支持nolog选项,你可以通过指定某些字符串在,正则表达式,或数组来设置忽略记录某些日志。
1
| app.use(log4js.connectLogger(logger, { level: 'auto', format: ':method :url', nolog: '\\.gif|\\.jpg$' }));
|
同样的,如果设置context
选项为true
,则log4js.connectLogger
可以向上下文(context)中添加express的响应(response),应用可以在layout或者appender中使用它
1
| app.use(log4js.connectLogger(logger, { context: true }));
|
在layout中使用:
1 2 3 4 5 6
| log4js.addLayout('customLayout', () => { return (loggingEvent) => { const res = loggingEvent.context.res; return util.format(...loggingEvent.data, res ? `status: ${res.statusCode}` : ''); }; });
|
nolog值示例
我的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const log4js = require("log4js"); var express = require('express');
log4js.configure({ appenders: { access: { type: "file", filename: 'express_access.log'}, console: { type: "console" }, }, categories: { default:{appenders:["console"],level:"debug"}, express_access: { appenders: ["access","console"], level: "info" },
}, }); var logger = log4js.getLogger("express_access") var app = express(); app.use(log4js.connectLogger(logger, { level: "auto", format: `:remote-addr - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"` })) app.listen(3000);
|
这样一个打印到控制台同时会输出到express_access.log的基于log4js的express的access日志就完成了