winston-middleware 0.1.2 → 0.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.
Files changed (4) hide show
  1. package/Readme.md +66 -12
  2. package/index.js +142 -59
  3. package/package.json +3 -4
  4. package/test/test.js +149 -8
package/Readme.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## Usage
11
11
 
12
- winston-middleware provides middlewares for request and error logging of your express.js application.
12
+ winston-middleware provides middlewares for request and error logging of your express.js application. It uses 'whitelists' to select properties from the request and (new in 0.2.x) response objects.
13
13
 
14
14
  ### Error Logging
15
15
 
@@ -17,7 +17,7 @@ Use `expressWinston.errorLogger(options)` to create a middleware that log the er
17
17
 
18
18
  ``` js
19
19
  app.use(app.router); // notice how the router goes first.
20
- app.use(expressWinston.errorHandler({
20
+ app.use(expressWinston.errorLogger({
21
21
  transports: [
22
22
  new winston.transports.Console({
23
23
  json: true,
@@ -29,6 +29,13 @@ Use `expressWinston.errorLogger(options)` to create a middleware that log the er
29
29
 
30
30
  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.
31
31
 
32
+ ### Options
33
+
34
+ ``` js
35
+ transports: [<WinstonTransport>], // list of all winston transports instances to use.
36
+ level: String // log level to use, the default is "info".
37
+ ```
38
+
32
39
  ### Request Logging
33
40
 
34
41
  Use `expressWinston.logger(options)` to create a middleware to log your HTTP requests.
@@ -46,9 +53,9 @@ Use `expressWinston.logger(options)` to create a middleware to log your HTTP req
46
53
  app.use(app.router); // notice how the router goes after the logger.
47
54
  ```
48
55
 
49
- ## Example
56
+ ## Examples
50
57
 
51
- ``` js
58
+ ``` js
52
59
  var express = require('express');
53
60
  var expressWinston = require('winston-middleware');
54
61
  var winston = require('winston'); // for transports.Console
@@ -69,8 +76,8 @@ Use `expressWinston.logger(options)` to create a middleware to log your HTTP req
69
76
 
70
77
  app.use(app.router);
71
78
 
72
- // winston-middleware errorHandler makes sense AFTER the router.
73
- app.use(expressWinston.errorHandler({
79
+ // winston-middleware errorLogger makes sense AFTER the router.
80
+ app.use(expressWinston.errorLogger({
74
81
  transports: [
75
82
  new winston.transports.Console({
76
83
  json: true,
@@ -80,7 +87,7 @@ Use `expressWinston.logger(options)` to create a middleware to log your HTTP req
80
87
  }));
81
88
 
82
89
  // Optionally you can include your custom error handler after the logging.
83
- app.use(express.errorHandler({
90
+ app.use(express.errorLogger({
84
91
  dumpExceptions: true,
85
92
  showStack: true
86
93
  }));
@@ -120,9 +127,13 @@ Browse `/` to see a regular HTTP logging like this:
120
127
  "originalUrl": "/",
121
128
  "query": {}
122
129
  },
130
+ "res": {
131
+ "statusCode": 200
132
+ },
133
+ "responseTime" : 12,
123
134
  "level": "info",
124
135
  "message": "HTTP GET /favicon.ico"
125
- }
136
+ }
126
137
 
127
138
  Browse `/error` will show you how winston-middleware handles and logs the errors in the express pipeline like this:
128
139
 
@@ -199,23 +210,66 @@ Browse `/error` will show you how winston-middleware handles and logs the errors
199
210
  "message": "middlewareError"
200
211
  }
201
212
 
213
+ ## Whitelists
214
+ New in version 0.2.x is the ability to add whitelist elements in a route. winston-middleware adds a `_routeWhitelists` object to the `req`uest, containing `.body`, `.req` and .res` properties, to which you can set an array of 'whitelist' parameters to include in the log, specific to the route in question:
215
+
216
+ ``` js
217
+ app.post('/user/register', function(req, res, next) {
218
+ req._routeWhitelists.body = ['username', 'email', 'age']; // But not 'password' or 'confirm-password' or 'top-secret'
219
+ req._routeWhitelists.res = ['_headers'];
220
+ });
221
+ ```
222
+
223
+ Post to `/user/register` would give you something like the following:
224
+
225
+ {
226
+ "req": {
227
+ "httpVersion": "1.1",
228
+ "headers": {
229
+ "host": "localhost:3000",
230
+ "connection": "keep-alive",
231
+ "accept": "*/*",
232
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
233
+ "accept-encoding": "gzip,deflate,sdch",
234
+ "accept-language": "en-US,en;q=0.8,es-419;q=0.6,es;q=0.4",
235
+ "accept-charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
236
+ "cookie": "connect.sid=nGspCCSzH1qxwNTWYAoexI23.seE%2B6Whmcwd"
237
+ },
238
+ "url": "/",
239
+ "method": "GET",
240
+ "originalUrl": "/",
241
+ "query": {},
242
+ "body": {
243
+ "username": "foo",
244
+ "email": "foo@bar.com",
245
+ "age": "72"
246
+ }
247
+ },
248
+ "res": {
249
+ "statusCode": 200
250
+ },
251
+ "responseTime" : 12,
252
+ "level": "info",
253
+ "message": "HTTP GET /favicon.ico"
254
+ }
255
+
202
256
  ## Tests
203
257
 
204
258
  npm test
205
259
 
206
260
  ## Issues and Collaboration
207
261
 
208
- * Add option to set the log level.
209
- * Add support for filtering of __req.body__. At this moment `body` is not included in the logging because it can contain sensitive fields like 'password' or 'password_confirmation'.
210
262
  * Implement a chain of requestFilters. Currently only one requestFilter is allowed in the options.
211
263
 
212
- We are accepting pull-request for this features.
264
+ We are accepting pull-request for these features.
213
265
 
214
266
  If you ran into any problems, please use the project [Issues section](https://github.com/firebaseco/winston-middleware/issues) to search or post any bug.
215
267
 
216
268
  ## Contributors
217
269
 
218
- * Johan (author). Email: *johan@firebase.co*
270
+ * [Johan Hernandez](https://github.com/thepumpkin1979) (https://github.com/thepumpkin1979)
271
+ * [Lars Jacob](https://github.com/jaclar) (https://github.com/jaclar)
272
+ * [Jonathan Lomas](https://github.com/floatingLomas) (https://github.com/floatingLomas)
219
273
 
220
274
  ## MIT License
221
275
 
package/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  // Copyright (c) 2012 Firebase.co and Contributors - http://www.firebase.co
2
- //
2
+ //
3
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  // of this software and associated documentation files (the "Software"), to deal
5
5
  // in the Software without restriction, including without limitation the rights
6
6
  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
7
  // copies of the Software, and to permit persons to whom the Software is
8
8
  // furnished to do so, subject to the following conditions:
9
- //
9
+ //
10
10
  // The above copyright notice and this permission notice shall be included in
11
11
  // all copies or substantial portions of the Software.
12
- //
12
+ //
13
13
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
14
  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
15
  // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
@@ -18,88 +18,171 @@
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  // THE SOFTWARE.
20
20
  //
21
-
22
21
  var winston = require('winston');
23
- var async = require('async');
24
22
  var util = require('util');
25
23
 
26
- // default list of properties in the request object that are allowed to be logged.
27
- // these properties will be safely included in the meta of the log.
28
- // 'body' is not included in this list because it can contains passwords and stuff that are sensitive for logging.
29
- // TODO: Include 'body' and get the defaultRequestFilter to filter the inner properties like 'password' or 'password_confirmation', etc. Pull requests anyone?
24
+ /**
25
+ * A default list of properties in the request object that are allowed to be logged.
26
+ * These properties will be safely included in the meta of the log.
27
+ * 'body' is not included in this list because it can contains passwords and stuff that are sensitive for logging.
28
+ * TODO: Include 'body' and get the defaultRequestFilter to filter the inner properties like 'password' or 'password_confirmation', etc. Pull requests anyone?
29
+ * @type {Array}
30
+ */
30
31
  var requestWhitelist = ['url', 'headers', 'method', 'httpVersion', 'originalUrl', 'query'];
31
32
 
32
- // default function to filter the properties of the req object.
33
- var defaultRequestFilter = function(req, propName) {
34
- return req[propName];
33
+ /**
34
+ * A default list of properties in the request body that are allowed to be logged.
35
+ * This will normally be empty here, since it should be done at the route level.
36
+ * @type {Array}
37
+ */
38
+ var bodyWhitelist = [];
39
+
40
+ /**
41
+ * A default list of properties in the response object that are allowed to be logged.
42
+ * These properties will be safely included in the meta of the log.
43
+ * @type {Array}
44
+ */
45
+ var responseWhitelist = ['statusCode'];
46
+
47
+ /**
48
+ * A default function to filter the properties of the req object.
49
+ * @param req
50
+ * @param propName
51
+ * @return {*}
52
+ */
53
+ var defaultRequestFilter = function (req, propName) {
54
+ return req[propName];
35
55
  };
36
56
 
37
- function filterRequest(originalReq, initialFilter) {
38
- var req = {};
39
- Object.keys(originalReq).forEach(function(propName) {
40
- // if the property is not in the whitelist, we return undefined so is not logged as part of the meta.
41
- if(requestWhitelist.indexOf(propName) == -1) return;
42
- var value = initialFilter(originalReq, propName);
43
- if(typeof(value) !== 'undefined') {
44
- req[propName] = value;
45
- }
46
- });
47
- return req;
57
+ /**
58
+ * A default function to filter the properties of the res object.
59
+ * @param res
60
+ * @param propName
61
+ * @return {*}
62
+ */
63
+ var defaultResponseFilter = function (req, propName) {
64
+ return req[propName];
48
65
  };
49
66
 
50
- //
67
+ function filterObject(originalObj, whiteList, initialFilter) {
68
+
69
+ var obj = {};
70
+
71
+ [].concat(whiteList).forEach(function (propName) {
72
+ var value = initialFilter(originalObj, propName);
73
+
74
+ if(typeof (value) !== 'undefined') {
75
+ obj[propName] = value;
76
+ };
77
+ });
78
+
79
+ return obj;
80
+ }
81
+
82
+ //
51
83
  // ### function errorLogger(options)
52
84
  // #### @options {Object} options to initialize the middleware.
53
85
  //
86
+
87
+
54
88
  function errorLogger(options) {
55
- if(!options) throw new Error("options are required by winston-middleware middleware");
56
- if(!options.transports || !(options.transports.length > 0)) throw new Error("transports are required by winston-middleware middleware");
57
- options.requestFilter = options.requestFilter || defaultRequestFilter;
58
- return function(err, req, res, next) {
59
- // let winston gather all the error data.
60
- var exceptionMeta = winston.exception.getAllInfo(err);
61
- exceptionMeta.req = filterRequest(req, options.requestFilter);
62
-
63
- function logOnTransport(transport, nextTransport) {
64
- return transport.logException('middlewareError', exceptionMeta, nextTransport);
65
- };
66
89
 
67
- function done() {
68
- return next(err);
90
+ ensureValidOptions(options);
91
+
92
+ options.requestFilter = options.requestFilter || defaultRequestFilter;
93
+
94
+ return function (err, req, res, next) {
95
+
96
+ // Let winston gather all the error data.
97
+ var exceptionMeta = winston.exception.getAllInfo(err);
98
+ exceptionMeta.req = filterObject(req, requestWhitelist, options.requestFilter);
99
+
100
+ // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
101
+ for(var i = 0; i < options.transports.length; i++) {
102
+ var transport = options.transports[i];
103
+ transport.logException('middlewareError', exceptionMeta, function () {
104
+ // Nothing to do here
105
+ });
106
+ }
107
+
108
+ next(err);
69
109
  };
70
- // iterate all the transports
71
- async.forEach(options.transports, logOnTransport, done);
72
- };
73
- };
110
+ }
74
111
 
75
- //
112
+ //
76
113
  // ### function logger(options)
77
114
  // #### @options {Object} options to initialize the middleware.
78
115
  //
116
+
117
+
79
118
  function logger(options) {
80
- if(!options) throw new Error("options are required by winston-middleware middleware");
81
- if(!options.transports || !(options.transports.length > 0)) throw new Error("transports are required by winston-middleware middleware");
82
- options.requestFilter = options.requestFilter || defaultRequestFilter;
83
- options.level = options.level || "info";
84
- return function(req, res, next) {
85
- var meta = {
86
- req: filterRequest(req, options.requestFilter)
87
- };
88
- var msg = util.format("HTTP %s %s", req.method, req.url);
89
119
 
90
- function logOnTransport(transport, nextTransport) {
91
- return transport.log(options.level, msg, meta, nextTransport);
92
- };
120
+ ensureValidOptions(options);
121
+
122
+ options.requestFilter = options.requestFilter || defaultRequestFilter;
123
+ options.responseFilter = options.responseFilter || defaultResponseFilter;
124
+ options.level = options.level || "info";
125
+
126
+ return function (req, res, next) {
127
+
128
+ req._startTime = (new Date);
129
+
130
+ req._routeWhitelists = {
131
+ req: [],
132
+ res: [],
133
+ body: []
134
+ };
135
+
136
+ // Manage to get information from the response too, just like Connect.logger does:
137
+ var end = res.end;
138
+ res.end = function(chunk, encoding) {
139
+ var responseTime = (new Date) - req._startTime;
140
+
141
+ res.end = end;
142
+ res.end(chunk, encoding);
93
143
 
94
- function done() {
95
- return next();
144
+ var meta = {};
145
+
146
+ var bodyWhitelist;
147
+
148
+ requestWhitelist = requestWhitelist.concat(req._routeWhitelists.req || []);
149
+ responseWhitelist = responseWhitelist.concat(req._routeWhitelists.res || []);
150
+
151
+ meta.req = filterObject(req, requestWhitelist, options.requestFilter);
152
+ meta.res = filterObject(res, responseWhitelist, options.responseFilter);
153
+
154
+ bodyWhitelist = req._routeWhitelists.body || [];
155
+
156
+ if (bodyWhitelist) {
157
+ meta.req.body = filterObject(req.body, bodyWhitelist, options.requestFilter);
158
+ };
159
+
160
+ meta.responseTime = responseTime;
161
+
162
+ var msg = util.format("HTTP %s %s", req.method, req.url);
163
+
164
+ // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
165
+ for(var i = 0; i < options.transports.length; i++) {
166
+ var transport = options.transports[i];
167
+ transport.log(options.level, msg, meta, function () {
168
+ // Nothing to do here
169
+ });
170
+ }
171
+ };
172
+
173
+ next();
96
174
  };
97
- // iterate all the transports
98
- async.forEach(options.transports, logOnTransport, done);
99
- };
175
+ }
176
+
177
+ function ensureValidOptions(options) {
178
+ if(!options) throw new Error("options are required by winston-middleware middleware");
179
+ if(!options.transports || !(options.transports.length > 0)) throw new Error("transports are required by winston-middleware middleware");
100
180
  };
101
181
 
102
182
  module.exports.errorLogger = errorLogger;
103
183
  module.exports.logger = logger;
104
184
  module.exports.requestWhitelist = requestWhitelist;
185
+ module.exports.bodyWhitelist = bodyWhitelist;
186
+ module.exports.responseWhitelist = responseWhitelist;
105
187
  module.exports.defaultRequestFilter = defaultRequestFilter;
188
+ module.exports.defaultResponseFilter = defaultResponseFilter;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "winston-middleware",
4
4
  "description": "express.js middleware for flatiron/winston",
5
5
  "keywords": ["winston", "flatiron", "logging", "express", "log", "error", "handler", "middleware"],
6
- "version": "0.1.2",
6
+ "version": "0.2.0",
7
7
  "repository": {
8
8
  "url": "https://github.com/firebaseco/winston-middleware.git"
9
9
  },
@@ -12,8 +12,7 @@
12
12
  "test": "node test/test.js"
13
13
  },
14
14
  "dependencies": {
15
- "winston": "0.6.x",
16
- "async": "0.1.x"
15
+ "winston": "0.6.x"
17
16
  },
18
17
  "devDependencies": {
19
18
  "vows": "0.6.x"
@@ -23,7 +22,7 @@
23
22
  },
24
23
  "licenses" : [
25
24
  {
26
- "type" : "MIT",
25
+ "type" : "MIT",
27
26
  "url" : "https://github.com/firebaseco/winston-middleware/blob/master/LICENSE"
28
27
  }
29
28
  ]
package/test/test.js CHANGED
@@ -15,12 +15,21 @@ vows.describe("exports").addBatch({
15
15
  topic: function() {
16
16
  return expressWinston;
17
17
  },
18
- "an array with all the properties whilelist in the req object": function(exports) {
18
+ "an array with all the properties whitelisted in the req object": function(exports) {
19
19
  assert.isArray(exports.requestWhitelist);
20
20
  },
21
+ "an array with all the properties whitelisted in the res object": function(exports) {
22
+ assert.isArray(exports.responseWhitelist);
23
+ },
24
+ "an array with all the properties whitelisted in the body object": function(exports) {
25
+ assert.isArray(exports.bodyWhitelist);
26
+ },
21
27
  "and the factory should contain a default request filter function": function(exports) {
22
28
  assert.isFunction(exports.defaultRequestFilter);
23
29
  },
30
+ "and the factory should contain a default response filter function": function(exports) {
31
+ assert.isFunction(exports.defaultResponseFilter);
32
+ },
24
33
  "it should export a function for the creation of error loggers middlewares": function(exports) {
25
34
  assert.isFunction(exports.errorLogger);
26
35
  },
@@ -61,7 +70,7 @@ vows.describe("errorLogger").addBatch({
61
70
  var middleware = factory({
62
71
  transports: [
63
72
  new MockTransport({
64
-
73
+
65
74
  })
66
75
  ]
67
76
  });
@@ -86,7 +95,7 @@ vows.describe("errorLogger").addBatch({
86
95
  params: {
87
96
  id: 20
88
97
  },
89
- filteredProperty: "value that should not be logged"
98
+ nonWhitelistedProperty: "value that should not be logged"
90
99
  };
91
100
  var res = {
92
101
 
@@ -134,7 +143,7 @@ vows.describe("errorLogger").addBatch({
134
143
  assert.deepEqual(result.log.meta.req.query, {
135
144
  val: '1'
136
145
  });
137
- assert.isUndefined(result.log.meta.req.filteredProperty);
146
+ assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
138
147
  },
139
148
  "the winston-middleware middleware should not swallow the pipeline error": function(result) {
140
149
  assert.isNotNull(result.pipelineError);
@@ -143,7 +152,7 @@ vows.describe("errorLogger").addBatch({
143
152
  }
144
153
  }).export(module);
145
154
 
146
- vows.describe("logger").addBatch({
155
+ vows.describe("logger 0.1.x").addBatch({
147
156
  "when I run the middleware factory": {
148
157
  topic: function() {
149
158
  return expressWinston.logger;
@@ -174,7 +183,7 @@ vows.describe("logger").addBatch({
174
183
  var middleware = factory({
175
184
  transports: [
176
185
  new MockTransport({
177
-
186
+
178
187
  })
179
188
  ]
180
189
  });
@@ -202,14 +211,15 @@ vows.describe("logger").addBatch({
202
211
  filteredProperty: "value that should not be logged"
203
212
  };
204
213
  var res = {
205
-
214
+ end: function(chunk, encoding) {}
206
215
  };
207
216
  var test = {
208
217
  req: req,
209
218
  res: res,
210
219
  log: {}
211
220
  };
212
- var next = function() {
221
+ var next = function(_req, _res, next) {
222
+ res.end();
213
223
  return callback(null, test);
214
224
  };
215
225
 
@@ -241,3 +251,134 @@ vows.describe("logger").addBatch({
241
251
  }
242
252
  }
243
253
  }).export(module);
254
+
255
+ vows.describe("logger 0.2.x").addBatch({
256
+ "when I run the middleware factory": {
257
+ topic: function() {
258
+ return expressWinston.logger;
259
+ },
260
+ "without options": {
261
+ "an error should be raised": function(factory) {
262
+ assert.throws(function() {
263
+ factory();
264
+ }, Error);
265
+ }
266
+ },
267
+ "without any transport specified": {
268
+ "an error should be raised": function(factory) {
269
+ assert.throws(function() {
270
+ factory({});
271
+ }, Error);
272
+ }
273
+ },
274
+ "with an empty list of transports": {
275
+ "an error should be raised": function(factory) {
276
+ assert.throws(function() {
277
+ factory({transports:[]});
278
+ }, Error);
279
+ }
280
+ },
281
+ "with proper options": {
282
+ "the result should be a function with three arguments that fit req, res, next": function (factory) {
283
+ var middleware = factory({
284
+ transports: [
285
+ new MockTransport({
286
+
287
+ })
288
+ ]
289
+ });
290
+ assert.equal(middleware.length, 3);
291
+ }
292
+ }
293
+ },
294
+ "When the winston-middleware middleware is invoked in pipeline": {
295
+ topic: function() {
296
+ var factory = expressWinston.logger;
297
+ var callback = this.callback;
298
+ var req = {
299
+ url: "/hello?val=1",
300
+ headers: {
301
+ 'header-1': 'value 1'
302
+ },
303
+ method: 'GET',
304
+ query: {
305
+ val: '2'
306
+ },
307
+ originalUrl: "/hello?val=2",
308
+ params: {
309
+ id: 20
310
+ },
311
+ nonWhitelistedProperty: "value that should not be logged",
312
+ routeLevelAddedProperty: "value that should be logged",
313
+ body: {
314
+ username: 'bobby',
315
+ password: 'top-secret'
316
+ }
317
+ };
318
+ var res = {
319
+ statusCode: 200,
320
+ nonWhitelistedProperty: "value that should not be logged",
321
+ routeLevelAddedProperty: "value that should be logged",
322
+ end: function(chunk, encoding) {
323
+
324
+ }
325
+ };
326
+ var test = {
327
+ req: req,
328
+ res: res,
329
+ log: {}
330
+ };
331
+ var next = function(_req, _res, next) {
332
+ req._startTime = (new Date) - 125;
333
+
334
+ req._routeWhitelists.req = [ 'routeLevelAddedProperty' ];
335
+ req._routeWhitelists.body = [ 'username' ];
336
+
337
+ res.end();
338
+ return callback(null, test);
339
+ };
340
+
341
+ var transport = new MockTransport({});
342
+ transport.log = function(level, msg, meta, cb) {
343
+ test.transportInvoked = true;
344
+ test.log.level = level;
345
+ test.log.msg = msg;
346
+ test.log.meta = meta;
347
+ this.emit('logged');
348
+ return cb();
349
+ };
350
+ var middleware = factory({
351
+ transports: [transport]
352
+ });
353
+ middleware(req, res, next);
354
+ }
355
+ , "then the transport should be invoked": function(result){
356
+ assert.isTrue(result.transportInvoked);
357
+ }
358
+ , "the meta should contain a filtered request": function(result){
359
+ assert.isTrue(!!result.log.meta.req, "req should be defined in meta");
360
+ assert.isNotNull(result.log.meta.req);
361
+ assert.equal(result.log.meta.req.method, "GET");
362
+ assert.deepEqual(result.log.meta.req.query, { val: '2' });
363
+ assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
364
+
365
+ assert.isNotNull(result.log.meta.req.routeLevelAddedProperty);
366
+ }
367
+ , "the meta should contain a filtered request body": function(result) {
368
+ assert.deepEqual(result.log.meta.req.body, {username: 'bobby'});
369
+ assert.isUndefined(result.log.meta.req.body.password);
370
+ }
371
+ , "the meta should contain a filtered response": function(result){
372
+ assert.isTrue(!!result.log.meta.res, "res should be defined in meta");
373
+ assert.isNotNull(result.log.meta.res);
374
+ assert.equal(result.log.meta.res.statusCode, 200);
375
+ assert.isNotNull(result.log.meta.res.routeLevelAddedProperty);
376
+ }
377
+ , "the meta should contain a response time": function(result){
378
+ assert.isTrue(!!result.log.meta.responseTime, "responseTime should be defined in meta");
379
+ assert.isNotNull(result.log.meta.responseTime);
380
+ assert.isTrue(result.log.meta.responseTime > 120);
381
+ assert.isTrue(result.log.meta.responseTime < 130);
382
+ }
383
+ }
384
+ }).export(module);