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.
- package/Readme.md +66 -12
- package/index.js +142 -59
- package/package.json +3 -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.
|
|
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
|
-
##
|
|
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
|
|
73
|
-
app.use(expressWinston.
|
|
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.
|
|
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
|
|
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 (
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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.
|
|
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);
|