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 CHANGED
@@ -1,10 +1,10 @@
1
1
  language: node_js
2
2
  node_js:
3
- - "0.6"
4
- - "0.8"
5
3
  - "0.10"
6
4
  - "0.11"
7
5
  - "0.12"
6
+ - "4.2"
7
+ - "5.3"
8
8
  - "iojs"
9
9
 
10
10
  script:
package/Readme.md CHANGED
@@ -1,17 +1,17 @@
1
1
  # winston-middleware
2
- [![Build Status](https://secure.travis-ci.org/bithavoc/winston-middleware.png)](http://travis-ci.org/bithavoc/winston-middleware)
2
+ [![Monthly Downloads](https://img.shields.io/npm/dm/winston-middleware.svg)](https://www.npmjs.com/package/winston-middleware) [![Build Status](https://secure.travis-ci.org/bithavoc/winston-middleware.png)](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.3.x --save
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
- ### Error Logging
42
+ ### Request Logging
43
43
 
44
- Use `expressWinston.errorLogger(options)` to create a middleware that log the errors of the pipeline.
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(router); // notice how the router goes first.
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
- 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.
63
+ app.use(router); // notice how the router goes after the logger.
64
+ ```
61
65
 
62
- ### Options
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
- skip: function(req, res) // function to determine if logging is skipped, defaults to false
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
- 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)`.
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.logger(options)` to create a middleware to log your HTTP requests.
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(expressWinston.logger({
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
- app.use(router); // notice how the router goes after the logger.
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
- meta.res = res;
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
- meta.res.body = isJson ? JSON.parse(chunk) : chunk.toString();
240
+ logData.res.body = isJson ? JSON.parse(chunk) : chunk.toString();
228
241
  }
229
242
  }
230
243
 
231
- meta.req = filterObject(req, requestWhitelist, options.requestFilter);
232
- meta.res = filterObject(res, responseWhitelist, options.responseFilter);
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
- meta.responseTime = res.responseTime;
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.1.0",
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 >| coverage.html || true"
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.6.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
  });