mirror of
https://github.com/log4js-node/log4js-node.git
synced 2025-12-08 19:26:01 +00:00
Merge pull request #862 from leak4mk0/context-request
feat(connectLogger): add response to context
This commit is contained in:
commit
54bfa96a8d
@ -73,6 +73,26 @@ The log4js.connectLogger also supports a nolog option where you can specify a st
|
||||
app.use(log4js.connectLogger(logger, { level: 'auto', format: ':method :url', nolog: '\\.gif|\\.jpg$' }));
|
||||
```
|
||||
|
||||
The log4js.connectLogger can add a response of express to context if `context` flag is set to `true`.
|
||||
Application can use it in layouts or appenders.
|
||||
|
||||
In application:
|
||||
|
||||
```javascript
|
||||
app.use(log4js.connectLogger(logger, { context: true }));
|
||||
```
|
||||
|
||||
In layout:
|
||||
|
||||
```javascript
|
||||
log4js.addLayout('customLayout', () => {
|
||||
return (loggingEvent) => {
|
||||
const res = loggingEvent.context.res;
|
||||
return util.format(...loggingEvent.data, res ? `status: ${res.statusCode}` : '');
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
## Example nolog values
|
||||
|
||||
| nolog value | Will Not Log | Will Log |
|
||||
|
||||
@ -205,6 +205,7 @@ function matchRules(statusCode, currentLevel, ruleSet) {
|
||||
* - `level` A log4js levels instance. Supports also 'auto'
|
||||
* - `nolog` A string or RegExp to exclude target logs
|
||||
* - `statusRules` A array of rules for setting specific logging levels base on status codes
|
||||
* - `context` Whether to add a response of express to the context
|
||||
*
|
||||
* Tokens:
|
||||
*
|
||||
@ -274,12 +275,14 @@ module.exports = function getLogger(logger4js, options) {
|
||||
|
||||
const combinedTokens = assembleTokens(req, res, options.tokens || []);
|
||||
|
||||
if (options.context) thisLogger.addContext('res', res);
|
||||
if (typeof fmt === 'function') {
|
||||
const line = fmt(req, res, str => format(str, combinedTokens));
|
||||
if (line) thisLogger.log(level, line);
|
||||
} else {
|
||||
thisLogger.log(level, format(fmt, combinedTokens));
|
||||
}
|
||||
if (options.context) thisLogger.removeContext('res');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
112
test/tap/connect-context-test.js
Normal file
112
test/tap/connect-context-test.js
Normal file
@ -0,0 +1,112 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('tap').test;
|
||||
const EE = require('events').EventEmitter;
|
||||
const levels = require('../../lib/levels');
|
||||
|
||||
class MockLogger {
|
||||
constructor() {
|
||||
this.level = levels.TRACE;
|
||||
this.context = {};
|
||||
this.contexts = [];
|
||||
}
|
||||
|
||||
log() {
|
||||
this.contexts.push(Object.assign({}, this.context));
|
||||
}
|
||||
|
||||
isLevelEnabled(level) {
|
||||
return level.isGreaterThanOrEqualTo(this.level);
|
||||
}
|
||||
|
||||
addContext(key, value) {
|
||||
this.context[key] = value;
|
||||
}
|
||||
|
||||
removeContext(key) {
|
||||
delete this.context[key];
|
||||
}
|
||||
}
|
||||
|
||||
function MockRequest(remoteAddr, method, originalUrl) {
|
||||
this.socket = { remoteAddress: remoteAddr };
|
||||
this.originalUrl = originalUrl;
|
||||
this.method = method;
|
||||
this.httpVersionMajor = '5';
|
||||
this.httpVersionMinor = '0';
|
||||
this.headers = {};
|
||||
}
|
||||
|
||||
class MockResponse extends EE {
|
||||
constructor(code) {
|
||||
super();
|
||||
this.statusCode = code;
|
||||
this.cachedHeaders = {};
|
||||
}
|
||||
|
||||
end() {
|
||||
this.emit('finish');
|
||||
}
|
||||
|
||||
setHeader(key, value) {
|
||||
this.cachedHeaders[key.toLowerCase()] = value;
|
||||
}
|
||||
|
||||
getHeader(key) {
|
||||
return this.cachedHeaders[key.toLowerCase()];
|
||||
}
|
||||
|
||||
writeHead(code /* , headers */) {
|
||||
this.statusCode = code;
|
||||
}
|
||||
}
|
||||
|
||||
test('log4js connect logger', (batch) => {
|
||||
const clm = require('../../lib/connect-logger');
|
||||
|
||||
batch.test('with context config', (t) => {
|
||||
const ml = new MockLogger();
|
||||
const cl = clm(ml, { context: true });
|
||||
|
||||
t.beforeEach((done) => { ml.contexts = []; done(); });
|
||||
|
||||
t.test('response should be included in context', (assert) => {
|
||||
const contexts = ml.contexts;
|
||||
const req = new MockRequest('my.remote.addr', 'GET', 'http://url/hoge.png'); // not gif
|
||||
const res = new MockResponse(200);
|
||||
cl(req, res, () => { });
|
||||
res.end('chunk', 'encoding');
|
||||
|
||||
assert.type(contexts, 'Array');
|
||||
assert.equal(contexts.length, 1);
|
||||
assert.type(contexts[0].res, MockResponse);
|
||||
assert.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
batch.test('without context config', (t) => {
|
||||
const ml = new MockLogger();
|
||||
const cl = clm(ml, { });
|
||||
|
||||
t.beforeEach((done) => { ml.contexts = []; done(); });
|
||||
|
||||
t.test('response should not be included in context', (assert) => {
|
||||
const contexts = ml.contexts;
|
||||
const req = new MockRequest('my.remote.addr', 'GET', 'http://url/hoge.png'); // not gif
|
||||
const res = new MockResponse(200);
|
||||
cl(req, res, () => { });
|
||||
res.end('chunk', 'encoding');
|
||||
|
||||
assert.type(contexts, 'Array');
|
||||
assert.equal(contexts.length, 1);
|
||||
assert.type(contexts[0].res, undefined);
|
||||
assert.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
batch.end();
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user