-
Notifications
You must be signed in to change notification settings - Fork 983
/
Copy pathaudit.js
122 lines (101 loc) · 3.38 KB
/
audit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
'use strict';
var assert = require('assert-plus');
var bunyan = require('bunyan');
var HttpError = require('restify-errors').HttpError;
///--- API
/**
* Returns a Bunyan audit logger suitable to be used in a server.on('after')
* event. I.e.:
*
* server.on('after', restify.auditLogger({ log: myAuditStream }));
*
* This logs at the INFO level.
*
* @public
* @function auditLogger
* @param {Object} options at least a bunyan logger (log).
* @returns {Function} to be used in server.after.
*/
function auditLogger(options) {
assert.object(options, 'options');
assert.object(options.log, 'options.log');
var errSerializer = bunyan.stdSerializers.err;
if (options.log.serializers && options.log.serializers.err) {
errSerializer = options.log.serializers.err;
}
var log = options.log.child({
audit: true,
serializers: {
err: errSerializer,
req: function auditRequestSerializer(req) {
if (!req) {
return (false);
}
var timers = {};
(req.timers || []).forEach(function (time) {
var t = time.time;
var _t = Math.floor((1000000 * t[0]) +
(t[1] / 1000));
timers[time.name] = _t;
});
return ({
// account for native and queryParser plugin usage
query: (typeof req.query === 'function') ?
req.query() : req.query,
method: req.method,
url: req.url,
headers: req.headers,
httpVersion: req.httpVersion,
trailers: req.trailers,
version: req.version(),
body: options.body === true ?
req.body : undefined,
timers: timers,
clientClosed: req.clientClosed
});
},
res: function auditResponseSerializer(res) {
if (!res) {
return (false);
}
var body;
if (options.body === true) {
if (res._body instanceof HttpError) {
body = res._body.body;
} else {
body = res._body;
}
}
return ({
statusCode: res.statusCode,
headers: res._headers,
trailer: res._trailer || false,
body: body
});
}
}
});
function audit(req, res, route, err) {
var latency = res.get('Response-Time');
if (typeof (latency) !== 'number') {
latency = Date.now() - req._time;
}
var obj = {
remoteAddress: req.connection.remoteAddress,
remotePort: req.connection.remotePort,
req_id: req.getId(),
req: req,
res: res,
err: err,
latency: latency,
secure: req.secure,
_audit: true
};
log.info(obj, 'handled: %d', res.statusCode);
return (true);
}
return (audit);
}
///-- Exports
module.exports = auditLogger;