winston-middleware 1.3.1 → 2.0.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.
Potentially problematic release.
This version of winston-middleware might be problematic. Click here for more details.
- package/CHANGELOG.md +28 -0
- package/Readme.md +9 -12
- package/index.js +43 -26
- package/package.json +7 -4
- package/test/test.js +72 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
## 2.0.0
|
|
2
|
+
#### Breaking changes
|
|
3
|
+
* Make winston a peer dependency. `npm install --save winston` if you haven't already.
|
|
4
|
+
* `expressFormat` has no color by default. Add `colorize: true` to winston-middleware
|
|
5
|
+
options to enable the previous colorized output. ([#86](https://github.com/bithavoc/winston-middleware/issues/86))
|
|
6
|
+
* Drop support for inherited properties on the object provided to the `baseMeta` option. This is unlikely to actually break anyone's real-world setup.
|
|
7
|
+
|
|
8
|
+
## 1.4.2
|
|
9
|
+
* Upgrade winston to 1.1 ([#114](https://github.com/bithavoc/winston-middleware/issues/114))
|
|
10
|
+
|
|
11
|
+
## 1.4.1
|
|
12
|
+
* Don't throw exception on invalid JSON in response body ([#112](https://github.com/bithavoc/winston-middleware/issues/112))
|
|
13
|
+
|
|
14
|
+
## 1.4.0
|
|
15
|
+
* Allow custom log level for error logger ([#111](https://github.com/bithavoc/winston-middleware/pull/111))
|
|
16
|
+
|
|
17
|
+
## 1.3.1
|
|
18
|
+
* underscore -> lodash ([#88](https://github.com/bithavoc/winston-middleware/issues/88))
|
|
19
|
+
|
|
20
|
+
## 1.3.0
|
|
21
|
+
* Allow custom status levels ([#102](https://github.com/bithavoc/winston-middleware/pull/102))
|
|
22
|
+
* Add per-instance equivalents of all global white/blacklists ([#105](https://github.com/bithavoc/winston-middleware/pull/105))
|
|
23
|
+
* Allow user to override module-level whitelists and functions without having to worry about using the right object reference ([#92](https://github.com/bithavoc/winston-middleware/issues/92))
|
|
24
|
+
|
|
25
|
+
## 1.2.0
|
|
26
|
+
* Add `baseMeta` and `metaField` options ([#91](https://github.com/bithavoc/winston-middleware/pull/91))
|
|
27
|
+
* Document `requestFilter` and `responseFilter` options
|
|
28
|
+
* Drop support for node 0.6 and 0.8
|
package/Readme.md
CHANGED
|
@@ -5,13 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
npm install winston winston-middleware
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
14
|
-
npm install winston-middleware@0.x.x --save
|
|
10
|
+
(supports node >= 0.10)
|
|
15
11
|
|
|
16
12
|
## Usage
|
|
17
13
|
|
|
@@ -25,8 +21,8 @@ In `package.json`:
|
|
|
25
21
|
{
|
|
26
22
|
"dependencies": {
|
|
27
23
|
"...": "...",
|
|
28
|
-
"winston": "0.
|
|
29
|
-
"winston-middleware": "0.
|
|
24
|
+
"winston": "^2.0.0",
|
|
25
|
+
"winston-middleware": "^2.0.0",
|
|
30
26
|
"...": "..."
|
|
31
27
|
}
|
|
32
28
|
}
|
|
@@ -55,8 +51,8 @@ Use `expressWinston.logger(options)` to create a middleware to log your HTTP req
|
|
|
55
51
|
],
|
|
56
52
|
meta: true, // optional: control whether you want to log the meta data about the request (default to true)
|
|
57
53
|
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
|
|
59
|
-
|
|
54
|
+
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
|
|
55
|
+
colorize: true, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
|
|
60
56
|
ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response
|
|
61
57
|
}));
|
|
62
58
|
|
|
@@ -70,8 +66,8 @@ Use `expressWinston.logger(options)` to create a middleware to log your HTTP req
|
|
|
70
66
|
winstonInstance: <WinstonLogger>, // a winston logger instance. If this is provided the transports option is ignored.
|
|
71
67
|
level: String, // log level to use, the default is "info".
|
|
72
68
|
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
|
|
74
|
-
|
|
69
|
+
expressFormat: Boolean, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors when colorize set to true
|
|
70
|
+
colorize: Boolean, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
|
|
75
71
|
meta: Boolean, // control whether you want to log the meta data about the request (default to true).
|
|
76
72
|
baseMeta: Object, // default meta data to be added to log, this will be merged with the meta data.
|
|
77
73
|
metaField: String, // if defined, the meta data will be added in this field instead of the meta root object.
|
|
@@ -118,6 +114,7 @@ The logger needs to be added AFTER the express router(`app.router)`) and BEFORE
|
|
|
118
114
|
metaField: String, // if defined, the meta data will be added in this field instead of the meta root object.
|
|
119
115
|
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.
|
|
120
116
|
requestWhitelist: [String] // Array of request properties to log. Overrides global requestWhitelist for this instance
|
|
117
|
+
level: String // custom log level for errors (default is 'error')
|
|
121
118
|
```
|
|
122
119
|
|
|
123
120
|
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)`.
|
package/index.js
CHANGED
|
@@ -121,6 +121,7 @@ exports.errorLogger = function errorLogger(options) {
|
|
|
121
121
|
options.msg = options.msg || 'middlewareError';
|
|
122
122
|
options.baseMeta = options.baseMeta || {};
|
|
123
123
|
options.metaField = options.metaField || null;
|
|
124
|
+
options.level = options.level || 'error';
|
|
124
125
|
|
|
125
126
|
// Using mustache style templating
|
|
126
127
|
var template = _.template(options.msg, {
|
|
@@ -139,10 +140,10 @@ exports.errorLogger = function errorLogger(options) {
|
|
|
139
140
|
exceptionMeta = newMeta;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
exceptionMeta = _.
|
|
143
|
+
exceptionMeta = _.assign(exceptionMeta, options.baseMeta);
|
|
143
144
|
|
|
144
145
|
// This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
|
|
145
|
-
options.winstonInstance.log(
|
|
146
|
+
options.winstonInstance.log(options.level, template({err: err, req: req, res: res}), exceptionMeta);
|
|
146
147
|
|
|
147
148
|
next(err);
|
|
148
149
|
};
|
|
@@ -172,16 +173,11 @@ exports.logger = function logger(options) {
|
|
|
172
173
|
options.msg = options.msg || "HTTP {{req.method}} {{req.url}}";
|
|
173
174
|
options.baseMeta = options.baseMeta || {};
|
|
174
175
|
options.metaField = options.metaField || null;
|
|
175
|
-
options.
|
|
176
|
+
options.colorize = options.colorize || false;
|
|
176
177
|
options.expressFormat = options.expressFormat || false;
|
|
177
178
|
options.ignoreRoute = options.ignoreRoute || function () { return false; };
|
|
178
179
|
options.skip = options.skip || exports.defaultSkip;
|
|
179
180
|
|
|
180
|
-
// Using mustache style templating
|
|
181
|
-
var template = _.template(options.msg, {
|
|
182
|
-
interpolate: /\{\{(.+?)\}\}/g
|
|
183
|
-
});
|
|
184
|
-
|
|
185
181
|
return function (req, res, next) {
|
|
186
182
|
var currentUrl = req.originalUrl || req.url;
|
|
187
183
|
if (currentUrl && _.includes(options.ignoredRoutes, currentUrl)) return next();
|
|
@@ -215,15 +211,6 @@ exports.logger = function logger(options) {
|
|
|
215
211
|
if (res.statusCode >= 500) { options.level = options.statusLevels.error || "error"; }
|
|
216
212
|
};
|
|
217
213
|
|
|
218
|
-
if (options.colorStatus || options.expressFormat) {
|
|
219
|
-
// Palette from https://github.com/expressjs/morgan/blob/master/index.js#L205
|
|
220
|
-
var statusColor = 'green';
|
|
221
|
-
if (res.statusCode >= 500) statusColor = 'red';
|
|
222
|
-
else if (res.statusCode >= 400) statusColor = 'yellow';
|
|
223
|
-
else if (res.statusCode >= 300) statusColor = 'cyan';
|
|
224
|
-
var coloredStatusCode = chalk[statusColor](res.statusCode);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
214
|
var meta = {};
|
|
228
215
|
|
|
229
216
|
if(options.meta !== false) {
|
|
@@ -239,7 +226,7 @@ exports.logger = function logger(options) {
|
|
|
239
226
|
var isJson = (res._headers && res._headers['content-type']
|
|
240
227
|
&& res._headers['content-type'].indexOf('json') >= 0);
|
|
241
228
|
|
|
242
|
-
logData.res.body =
|
|
229
|
+
logData.res.body = bodyToString(chunk, isJson);
|
|
243
230
|
}
|
|
244
231
|
}
|
|
245
232
|
|
|
@@ -269,18 +256,32 @@ exports.logger = function logger(options) {
|
|
|
269
256
|
newMeta[options.metaField] = logData;
|
|
270
257
|
logData = newMeta;
|
|
271
258
|
}
|
|
272
|
-
meta = _.
|
|
259
|
+
meta = _.assign(meta, logData);
|
|
273
260
|
}
|
|
274
261
|
|
|
275
|
-
meta = _.
|
|
262
|
+
meta = _.assign(meta, options.baseMeta);
|
|
276
263
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
264
|
+
var expressMsgFormat = "{{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms";
|
|
265
|
+
if (options.colorize) {
|
|
266
|
+
// Palette from https://github.com/expressjs/morgan/blob/master/index.js#L205
|
|
267
|
+
var statusColor = 'green';
|
|
268
|
+
if (res.statusCode >= 500) statusColor = 'red';
|
|
269
|
+
else if (res.statusCode >= 400) statusColor = 'yellow';
|
|
270
|
+
else if (res.statusCode >= 300) statusColor = 'cyan';
|
|
271
|
+
|
|
272
|
+
expressMsgFormat = chalk.grey("{{req.method}} {{req.url}}") +
|
|
273
|
+
" " + chalk[statusColor]("{{res.statusCode}}") + " " +
|
|
274
|
+
chalk.grey("{{res.responseTime}}ms");
|
|
283
275
|
}
|
|
276
|
+
var msgFormat = !options.expressFormat ? options.msg : expressMsgFormat;
|
|
277
|
+
|
|
278
|
+
// Using mustache style templating
|
|
279
|
+
var template = _.template(msgFormat, {
|
|
280
|
+
interpolate: /\{\{(.+?)\}\}/g
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
var msg = template({req: req, res: res});
|
|
284
|
+
|
|
284
285
|
// This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
|
|
285
286
|
if (!options.skip(req, res)) {
|
|
286
287
|
options.winstonInstance.log(options.level, msg, meta);
|
|
@@ -291,6 +292,22 @@ exports.logger = function logger(options) {
|
|
|
291
292
|
};
|
|
292
293
|
};
|
|
293
294
|
|
|
295
|
+
function safeJSONParse(string) {
|
|
296
|
+
try {
|
|
297
|
+
return JSON.parse(string);
|
|
298
|
+
} catch (e) {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function bodyToString(body, isJSON) {
|
|
304
|
+
var stringBody = body && body.toString();
|
|
305
|
+
if (isJSON) {
|
|
306
|
+
return (safeJSONParse(body) || stringBody);
|
|
307
|
+
}
|
|
308
|
+
return stringBody;
|
|
309
|
+
}
|
|
310
|
+
|
|
294
311
|
function ensureValidOptions(options) {
|
|
295
312
|
if(!options) throw new Error("options are required by winston-middleware middleware");
|
|
296
313
|
if(!((options.transports && (options.transports.length > 0)) || options.winstonInstance))
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"middleware",
|
|
18
18
|
"colors"
|
|
19
19
|
],
|
|
20
|
-
"version": "
|
|
20
|
+
"version": "2.0.0",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "https://github.com/bithavoc/winston-middleware.git"
|
|
@@ -48,8 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"chalk": "~0.4.0",
|
|
51
|
-
"lodash": "~4.11.1"
|
|
52
|
-
"winston": "~1.0.0"
|
|
51
|
+
"lodash": "~4.11.1"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|
|
55
54
|
"blanket": "^1.2.2",
|
|
@@ -57,7 +56,11 @@
|
|
|
57
56
|
"node-mocks-http": "^1.5.1",
|
|
58
57
|
"promise": "^7.1.1",
|
|
59
58
|
"should": "^8.2.2",
|
|
60
|
-
"travis-cov": "^0.2.5"
|
|
59
|
+
"travis-cov": "^0.2.5",
|
|
60
|
+
"winston": ">=1.x"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"winston": ">=1.x"
|
|
61
64
|
},
|
|
62
65
|
"engines": {
|
|
63
66
|
"node": ">=0.10.0"
|
package/test/test.js
CHANGED
|
@@ -189,12 +189,19 @@ describe('winston-middleware', function () {
|
|
|
189
189
|
});
|
|
190
190
|
});
|
|
191
191
|
|
|
192
|
-
it('should find
|
|
192
|
+
it('should find the default level of "error"', function () {
|
|
193
193
|
return errorLoggerTestHelper().then(function (result) {
|
|
194
194
|
result.log.level.should.eql('error');
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
+
it('should find a custom level of "warn"', function () {
|
|
199
|
+
var testHelperOptions = {loggerOptions: {level:'warn'}};
|
|
200
|
+
return errorLoggerTestHelper(testHelperOptions).then(function (result) {
|
|
201
|
+
result.log.level.should.eql('warn');
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
198
205
|
it('should find a message of "middlewareError"', function () {
|
|
199
206
|
return errorLoggerTestHelper().then(function (result) {
|
|
200
207
|
result.log.msg.should.eql('middlewareError');
|
|
@@ -528,6 +535,35 @@ describe('winston-middleware', function () {
|
|
|
528
535
|
});
|
|
529
536
|
});
|
|
530
537
|
|
|
538
|
+
describe('when middleware function is invoked on a route that returns JSON', function() {
|
|
539
|
+
it('should parse JSON in response body', function() {
|
|
540
|
+
var bodyObject = { "message": "Hi! I\'m a chunk!" };
|
|
541
|
+
function next(req, res, next) {
|
|
542
|
+
// Set Content-Type in a couple different case types, just in case.
|
|
543
|
+
// Seems like the mock response doesn't quite handle the case
|
|
544
|
+
// translation on these right.
|
|
545
|
+
res.setHeader('Content-Type', 'application/json');
|
|
546
|
+
res.setHeader('content-type', 'application/json');
|
|
547
|
+
res.end(JSON.stringify(bodyObject));
|
|
548
|
+
}
|
|
549
|
+
return loggerTestHelper({next: next}).then(function(result) {
|
|
550
|
+
result.log.meta.res.body.should.eql(bodyObject);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it('should not blow up when response body is invalid JSON', function() {
|
|
555
|
+
function next(req, res, next) {
|
|
556
|
+
// Set Content-Type in a couple different case types, just in case.
|
|
557
|
+
// Seems like the mock response doesn't quite handle the case
|
|
558
|
+
// translation on these right.
|
|
559
|
+
res.setHeader('Content-Type', 'application/json');
|
|
560
|
+
res.setHeader('content-type', 'application/json');
|
|
561
|
+
res.end('}');
|
|
562
|
+
}
|
|
563
|
+
return loggerTestHelper({next: next});
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
|
|
531
567
|
describe('when middleware function is invoked on a route that should be ignored (by .ignoredRoutes)', function () {
|
|
532
568
|
var testHelperOptions = {
|
|
533
569
|
req: {url: '/ignored'}
|
|
@@ -550,6 +586,7 @@ describe('winston-middleware', function () {
|
|
|
550
586
|
it('should match the Express format when logging', function () {
|
|
551
587
|
var testHelperOptions = {
|
|
552
588
|
loggerOptions: {
|
|
589
|
+
colorize: true,
|
|
553
590
|
expressFormat: true
|
|
554
591
|
},
|
|
555
592
|
req: {
|
|
@@ -562,6 +599,40 @@ describe('winston-middleware', function () {
|
|
|
562
599
|
resultMsg.should.endWith('ms\u001b[39m');
|
|
563
600
|
});
|
|
564
601
|
});
|
|
602
|
+
|
|
603
|
+
it('should not emit colors when colorize option is false', function() {
|
|
604
|
+
var testHelperOptions = {
|
|
605
|
+
loggerOptions: {
|
|
606
|
+
colorize: false,
|
|
607
|
+
expressFormat: true
|
|
608
|
+
},
|
|
609
|
+
req: {
|
|
610
|
+
url: '/all-the-things'
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
return loggerTestHelper(testHelperOptions).then(function (result) {
|
|
614
|
+
var resultMsg = result.log.msg;
|
|
615
|
+
resultMsg.should.startWith('GET /all-the-things 200 ');
|
|
616
|
+
resultMsg.should.endWith('ms');
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
it('should not emit colors when colorize option is not present', function() {
|
|
621
|
+
var testHelperOptions = {
|
|
622
|
+
loggerOptions: {
|
|
623
|
+
colorize: false,
|
|
624
|
+
expressFormat: true
|
|
625
|
+
},
|
|
626
|
+
req: {
|
|
627
|
+
url: '/all-the-things'
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
return loggerTestHelper(testHelperOptions).then(function (result) {
|
|
631
|
+
var resultMsg = result.log.msg;
|
|
632
|
+
resultMsg.should.startWith('GET /all-the-things 200 ');
|
|
633
|
+
resultMsg.should.endWith('ms');
|
|
634
|
+
});
|
|
635
|
+
});
|
|
565
636
|
});
|
|
566
637
|
|
|
567
638
|
describe('msg option', function () {
|