winston-middleware 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +2 -2
- package/Readme.md +49 -29
- package/index.js +29 -7
- package/package.json +3 -3
- package/test/test.js +99 -1
package/.travis.yml
CHANGED
package/Readme.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# winston-middleware
|
|
2
|
-
[](http://travis-ci.org/bithavoc/winston-middleware)
|
|
2
|
+
[](https://www.npmjs.com/package/winston-middleware) [](http://travis-ci.org/bithavoc/winston-middleware)
|
|
3
3
|
|
|
4
4
|
> [winston](https://github.com/flatiron/winston) middleware for express.js
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
8
|
-
Newcomers should start with the latest branch which makes use of winston 1.x.x:
|
|
8
|
+
Newcomers should start with the latest branch which makes use of winston 1.x.x and supports node >= 0.10:
|
|
9
9
|
|
|
10
10
|
npm install winston-middleware
|
|
11
11
|
|
|
12
12
|
If you're already using winston-middleware, and want to stick with the stable version based on winston 0.9.x, you should instead do:
|
|
13
13
|
|
|
14
|
-
npm install winston-middleware@0.
|
|
14
|
+
npm install winston-middleware@0.x.x --save
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
@@ -39,64 +39,84 @@ var winston = require('winston'),
|
|
|
39
39
|
expressWinston = require('winston-middleware');
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
###
|
|
42
|
+
### Request Logging
|
|
43
43
|
|
|
44
|
-
Use `expressWinston.
|
|
44
|
+
Use `expressWinston.logger(options)` to create a middleware to log your HTTP requests.
|
|
45
45
|
|
|
46
46
|
``` js
|
|
47
47
|
var router = require('./my-express-router');
|
|
48
48
|
|
|
49
|
-
app.use(
|
|
50
|
-
app.use(expressWinston.errorLogger({
|
|
49
|
+
app.use(expressWinston.logger({
|
|
51
50
|
transports: [
|
|
52
51
|
new winston.transports.Console({
|
|
53
52
|
json: true,
|
|
54
53
|
colorize: true
|
|
55
54
|
})
|
|
56
|
-
]
|
|
55
|
+
],
|
|
56
|
+
meta: true, // optional: control whether you want to log the meta data about the request (default to true)
|
|
57
|
+
msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
|
|
58
|
+
expressFormat: true, // Use the default Express/morgan request formatting, with the same colors. Enabling this will override any msg and colorStatus if true. Will only output colors on transports with colorize set to true
|
|
59
|
+
colorStatus: true, // Color the status code, using the Express/morgan color palette (default green, 3XX cyan, 4XX yellow, 5XX red). Will not be recognized if expressFormat is true
|
|
60
|
+
ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response
|
|
57
61
|
}));
|
|
58
|
-
```
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
app.use(router); // notice how the router goes after the logger.
|
|
64
|
+
```
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
#### Options
|
|
63
67
|
|
|
64
68
|
``` js
|
|
65
69
|
transports: [<WinstonTransport>], // list of all winston transports instances to use.
|
|
66
|
-
winstonInstance: <WinstonLogger>, // a winston logger instance. If this is provided the transports option is ignored
|
|
70
|
+
winstonInstance: <WinstonLogger>, // a winston logger instance. If this is provided the transports option is ignored.
|
|
67
71
|
level: String, // log level to use, the default is "info".
|
|
72
|
+
msg: String // customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}", "HTTP {{req.method}} {{req.url}}".
|
|
73
|
+
expressFormat: Boolean, // Use the default Express/morgan request formatting, with the same colors. Enabling this will override any msg and colorStatus if true. Will only output colors on transports with colorize set to true
|
|
74
|
+
colorStatus: Boolean, // Color the status code, using the Express/morgan color palette (default green, 3XX cyan, 4XX yellow, 5XX red). Will not be recognized if expressFormat is true
|
|
75
|
+
meta: Boolean, // control whether you want to log the meta data about the request (default to true).
|
|
76
|
+
baseMeta: Object, // default meta data to be added to log, this will be merged with the meta data.
|
|
77
|
+
metaField: String, // if defined, the meta data will be added in this field instead of the meta root object.
|
|
68
78
|
statusLevels: Boolean // different HTTP status codes caused log messages to be logged at different levels (info/warn/error), the default is false
|
|
69
|
-
|
|
79
|
+
ignoreRoute: function (req, res) { return false; } // allows to skip some log messages based on request and/or response.
|
|
80
|
+
skip: function(req, res) { return false; } // function to determine if logging is skipped, defaults to false.
|
|
81
|
+
requestFilter: function (req, propName) { return req[propName]; } // A function to filter/return request values, defaults to returning all values allowed by whitelist. If the function returns undefined, the key/value will not be included in the meta.
|
|
82
|
+
responseFilter: function (res, propName) { return res[propName]; } // A function to filter/return response values, defaults to returning all values allowed by whitelist. If the function returns undefined, the key/value will not be included in the meta.
|
|
70
83
|
```
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Alternatively, if you're using a winston logger instance elsewhere and have already set up levels and transports, pass the instance into expressWinston with the `winstonInstance` option. The `transports` option is then ignored.
|
|
75
|
-
|
|
76
|
-
### Request Logging
|
|
85
|
+
### Error Logging
|
|
77
86
|
|
|
78
|
-
Use `expressWinston.
|
|
87
|
+
Use `expressWinston.errorLogger(options)` to create a middleware that log the errors of the pipeline.
|
|
79
88
|
|
|
80
89
|
``` js
|
|
81
90
|
var router = require('./my-express-router');
|
|
82
91
|
|
|
83
|
-
app.use(
|
|
92
|
+
app.use(router); // notice how the router goes first.
|
|
93
|
+
app.use(expressWinston.errorLogger({
|
|
84
94
|
transports: [
|
|
85
95
|
new winston.transports.Console({
|
|
86
96
|
json: true,
|
|
87
97
|
colorize: true
|
|
88
98
|
})
|
|
89
|
-
]
|
|
90
|
-
meta: true, // optional: control whether you want to log the meta data about the request (default to true)
|
|
91
|
-
msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
|
|
92
|
-
expressFormat: true, // Use the default Express/morgan request formatting, with the same colors. Enabling this will override any msg and colorStatus if true. Will only output colors on transports with colorize set to true
|
|
93
|
-
colorStatus: true, // Color the status code, using the Express/morgan color palette (default green, 3XX cyan, 4XX yellow, 5XX red). Will not be recognized if expressFormat is true
|
|
94
|
-
ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response
|
|
99
|
+
]
|
|
95
100
|
}));
|
|
101
|
+
```
|
|
96
102
|
|
|
97
|
-
|
|
103
|
+
The logger needs to be added AFTER the express router(`app.router)`) and BEFORE any of your custom error handlers(`express.handler`). Since winston-middleware will just log the errors and not __handle__ them, you can still use your custom error handler like `express.handler`, just be sure to put the logger before any of your handlers.
|
|
104
|
+
|
|
105
|
+
#### Options
|
|
106
|
+
|
|
107
|
+
``` js
|
|
108
|
+
transports: [<WinstonTransport>], // list of all winston transports instances to use.
|
|
109
|
+
winstonInstance: <WinstonLogger>, // a winston logger instance. If this is provided the transports option is ignored
|
|
110
|
+
msg: String // customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}", "HTTP {{req.method}} {{req.url}}".
|
|
111
|
+
baseMeta: Object, // default meta data to be added to log, this will be merged with the error data.
|
|
112
|
+
metaField: String, // if defined, the meta data will be added in this field instead of the meta root object.
|
|
113
|
+
requestFilter: function (req, propName) { return req[propName]; } // A function to filter/return request values, defaults to returning all values allowed by whitelist. If the function returns undefined, the key/value will not be included in the meta.
|
|
98
114
|
```
|
|
99
115
|
|
|
116
|
+
To use winston's existing transports, set `transports` to the values (as in key-value) of the `winston.default.transports` object. This may be done, for example, by using underscorejs: `transports: _.values(winston.default.transports)`.
|
|
117
|
+
|
|
118
|
+
Alternatively, if you're using a winston logger instance elsewhere and have already set up levels and transports, pass the instance into expressWinston with the `winstonInstance` option. The `transports` option is then ignored.
|
|
119
|
+
|
|
100
120
|
## Examples
|
|
101
121
|
|
|
102
122
|
``` js
|
|
@@ -354,11 +374,11 @@ Run the basic Mocha tests:
|
|
|
354
374
|
|
|
355
375
|
Run the Travis-CI tests (which will fail with < 100% coverage):
|
|
356
376
|
|
|
357
|
-
npm test-travis
|
|
377
|
+
npm run test-travis
|
|
358
378
|
|
|
359
379
|
Generate the `coverage.html` coverage report:
|
|
360
380
|
|
|
361
|
-
npm test-coverage
|
|
381
|
+
npm run test-coverage
|
|
362
382
|
|
|
363
383
|
## Issues and Collaboration
|
|
364
384
|
|
package/index.js
CHANGED
|
@@ -121,6 +121,8 @@ function errorLogger(options) {
|
|
|
121
121
|
options.requestFilter = options.requestFilter || defaultRequestFilter;
|
|
122
122
|
options.winstonInstance = options.winstonInstance || (new winston.Logger ({ transports: options.transports }));
|
|
123
123
|
options.msg = options.msg || 'middlewareError';
|
|
124
|
+
options.baseMeta = options.baseMeta || {};
|
|
125
|
+
options.metaField = options.metaField || null;
|
|
124
126
|
|
|
125
127
|
// Using mustache style templating
|
|
126
128
|
var template = _.template(options.msg, null, {
|
|
@@ -133,6 +135,14 @@ function errorLogger(options) {
|
|
|
133
135
|
var exceptionMeta = winston.exception.getAllInfo(err);
|
|
134
136
|
exceptionMeta.req = filterObject(req, requestWhitelist, options.requestFilter);
|
|
135
137
|
|
|
138
|
+
if (options.metaField) {
|
|
139
|
+
var newMeta = {};
|
|
140
|
+
newMeta[options.metaField] = exceptionMeta;
|
|
141
|
+
exceptionMeta = newMeta;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
exceptionMeta = _.extend(exceptionMeta, options.baseMeta);
|
|
145
|
+
|
|
136
146
|
// This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
|
|
137
147
|
options.winstonInstance.log('error', template({err: err, req: req, res: res}), exceptionMeta);
|
|
138
148
|
|
|
@@ -157,6 +167,8 @@ function logger(options) {
|
|
|
157
167
|
options.level = options.level || "info";
|
|
158
168
|
options.statusLevels = options.statusLevels || false;
|
|
159
169
|
options.msg = options.msg || "HTTP {{req.method}} {{req.url}}";
|
|
170
|
+
options.baseMeta = options.baseMeta || {};
|
|
171
|
+
options.metaField = options.metaField || null;
|
|
160
172
|
options.colorStatus = options.colorStatus || false;
|
|
161
173
|
options.expressFormat = options.expressFormat || false;
|
|
162
174
|
options.ignoreRoute = options.ignoreRoute || function () { return false; };
|
|
@@ -212,24 +224,25 @@ function logger(options) {
|
|
|
212
224
|
var meta = {};
|
|
213
225
|
|
|
214
226
|
if(options.meta !== false) {
|
|
227
|
+
var logData = {};
|
|
215
228
|
var bodyWhitelist, blacklist;
|
|
216
229
|
|
|
217
230
|
requestWhitelist = requestWhitelist.concat(req._routeWhitelists.req || []);
|
|
218
231
|
responseWhitelist = responseWhitelist.concat(req._routeWhitelists.res || []);
|
|
219
232
|
|
|
220
|
-
|
|
233
|
+
logData.res = res;
|
|
221
234
|
|
|
222
235
|
if (_.contains(responseWhitelist, 'body')) {
|
|
223
236
|
if (chunk) {
|
|
224
237
|
var isJson = (res._headers && res._headers['content-type']
|
|
225
238
|
&& res._headers['content-type'].indexOf('json') >= 0);
|
|
226
239
|
|
|
227
|
-
|
|
240
|
+
logData.res.body = isJson ? JSON.parse(chunk) : chunk.toString();
|
|
228
241
|
}
|
|
229
242
|
}
|
|
230
243
|
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
logData.req = filterObject(req, requestWhitelist, options.requestFilter);
|
|
245
|
+
logData.res = filterObject(res, responseWhitelist, options.responseFilter);
|
|
233
246
|
|
|
234
247
|
bodyWhitelist = req._routeWhitelists.body || [];
|
|
235
248
|
blacklist = _.union(bodyBlacklist, (req._routeBlacklists.body || []));
|
|
@@ -244,12 +257,21 @@ function logger(options) {
|
|
|
244
257
|
filteredBody = filterObject(req.body, bodyWhitelist, options.requestFilter);
|
|
245
258
|
}
|
|
246
259
|
}
|
|
247
|
-
|
|
248
|
-
if (filteredBody) meta.req.body = filteredBody;
|
|
249
260
|
|
|
250
|
-
|
|
261
|
+
if (filteredBody) logData.req.body = filteredBody;
|
|
262
|
+
|
|
263
|
+
logData.responseTime = res.responseTime;
|
|
264
|
+
|
|
265
|
+
if (options.metaField) {
|
|
266
|
+
var newMeta = {}
|
|
267
|
+
newMeta[options.metaField] = logData;
|
|
268
|
+
logData = newMeta;
|
|
269
|
+
}
|
|
270
|
+
meta = _.extend(meta, logData);
|
|
251
271
|
}
|
|
252
272
|
|
|
273
|
+
meta = _.extend(meta, options.baseMeta);
|
|
274
|
+
|
|
253
275
|
if(options.expressFormat) {
|
|
254
276
|
var msg = chalk.grey(req.method + " " + req.url || req.url)
|
|
255
277
|
+ " " + chalk[statusColor](res.statusCode)
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"middleware",
|
|
18
18
|
"colors"
|
|
19
19
|
],
|
|
20
|
-
"version": "1.
|
|
20
|
+
"version": "1.2.0",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "https://github.com/bithavoc/winston-middleware.git"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"test": "node_modules/.bin/mocha --reporter spec",
|
|
32
32
|
"test-travis": "node_modules/.bin/mocha --require blanket --reporter travis-cov",
|
|
33
|
-
"test-coverage": "node_modules/.bin/mocha --require blanket --reporter html-cov
|
|
33
|
+
"test-coverage": "node_modules/.bin/mocha --require blanket --reporter html-cov > coverage.html || true"
|
|
34
34
|
},
|
|
35
35
|
"config": {
|
|
36
36
|
"travis-cov": {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"travis-cov": "~0.2.5"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
|
-
"node": ">=0.
|
|
62
|
+
"node": ">=0.10.0"
|
|
63
63
|
},
|
|
64
64
|
"license": "MIT",
|
|
65
65
|
"contributors": [
|
package/test/test.js
CHANGED
|
@@ -194,6 +194,46 @@ describe('expressWinston', function () {
|
|
|
194
194
|
});
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
describe('log.metaField', function (done) {
|
|
199
|
+
var result;
|
|
200
|
+
|
|
201
|
+
before(function (done) {
|
|
202
|
+
setUp();
|
|
203
|
+
|
|
204
|
+
var originalError = new Error('This is the Error');
|
|
205
|
+
|
|
206
|
+
var test = {
|
|
207
|
+
req: req,
|
|
208
|
+
res: res,
|
|
209
|
+
log: {},
|
|
210
|
+
originalError: originalError,
|
|
211
|
+
pipelineError: null
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
function next(pipelineError) {
|
|
215
|
+
test.pipelineError = pipelineError;
|
|
216
|
+
|
|
217
|
+
result = test;
|
|
218
|
+
|
|
219
|
+
return done();
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
var middleware = expressWinston.errorLogger({
|
|
223
|
+
transports: [new MockTransport(test)],
|
|
224
|
+
metaField: 'metaField'
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
middleware(originalError, req, res, next);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe('when using custom metaField', function () {
|
|
231
|
+
|
|
232
|
+
it('should be logged', function () {
|
|
233
|
+
result.log.meta.metaField.req.should.be.ok;
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
197
237
|
});
|
|
198
238
|
|
|
199
239
|
describe('.logger()', function () {
|
|
@@ -588,7 +628,7 @@ describe('expressWinston', function () {
|
|
|
588
628
|
});
|
|
589
629
|
});
|
|
590
630
|
});
|
|
591
|
-
|
|
631
|
+
|
|
592
632
|
describe('log.skip', function () {
|
|
593
633
|
var result;
|
|
594
634
|
|
|
@@ -655,6 +695,64 @@ describe('expressWinston', function () {
|
|
|
655
695
|
});
|
|
656
696
|
});
|
|
657
697
|
});
|
|
698
|
+
|
|
699
|
+
describe('log.metaField', function () {
|
|
700
|
+
var result;
|
|
701
|
+
|
|
702
|
+
function logMetaFieldSetup(url, metaField, done) {
|
|
703
|
+
setUp({
|
|
704
|
+
url: url || '/an-url'
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
var test = {
|
|
708
|
+
req: req,
|
|
709
|
+
res: res,
|
|
710
|
+
log: {}
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
function next(_req, _res, next) {
|
|
714
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
715
|
+
|
|
716
|
+
result = test;
|
|
717
|
+
|
|
718
|
+
return done();
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
var loggerOptions = {
|
|
722
|
+
transports: [new MockTransport(test)]
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
if (metaField) {
|
|
726
|
+
loggerOptions.metaField = metaField;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
var middleware = expressWinston.logger(loggerOptions);
|
|
730
|
+
|
|
731
|
+
middleware(req, res, next);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
describe('when default', function () {
|
|
735
|
+
|
|
736
|
+
before(function (done) {
|
|
737
|
+
logMetaFieldSetup('/url-of-sandwich', null, done);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it('should be logged', function () {
|
|
741
|
+
result.log.meta.req.should.be.ok;
|
|
742
|
+
});
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
describe('when using custom metaField', function () {
|
|
746
|
+
|
|
747
|
+
before(function (done) {
|
|
748
|
+
logMetaFieldSetup('/url-of-sandwich', 'metaField', done);
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
it('should be logged', function () {
|
|
752
|
+
result.log.meta.metaField.req.should.be.ok;
|
|
753
|
+
});
|
|
754
|
+
});
|
|
755
|
+
});
|
|
658
756
|
});
|
|
659
757
|
});
|
|
660
758
|
});
|