exclude domain keys on error objects for 'err' serializer

This commit is contained in:
Trent Mick 2013-03-01 16:58:56 -08:00
parent b2438ddb2c
commit f096b303c1
6 changed files with 52 additions and 39 deletions

View file

@ -8,7 +8,15 @@ Known issues:
## bunyan 0.18.3 (not yet released) ## bunyan 0.18.3 (not yet released)
(nothing yet) - Change the `bunyan.stdSerializers.err` serializer for errors to *exclude*
[the "domain*" keys](http://nodejs.org/docs/latest/api/all.html#all_additions_to_error_objects).
`err.domain` will include its assigned members which can arbitrarily large
objects that are not intended for logging.
- Make the "dtrace-provider" dependency optional. I hate to do this, but
installing bunyan on Windows is made very difficult with this as a required
dep. Even though "dtrace-provider" stubs out for non-dtrace-y platforms,
without a compiler and Python around, node-gyp just falls over.
## bunyan 0.18.2 ## bunyan 0.18.2

View file

@ -1,3 +1,4 @@
- upgrade to dtrace-provider@0.2.8 when it comes for 0.9 compat
- man page for the bunyan CLI (refer to it in the readme) - man page for the bunyan CLI (refer to it in the readme)
- `tail -f`-like support - `tail -f`-like support
- 1.0 with `v: 1` in log records. Fwd/bwd compat in `bunyan` CLI - 1.0 with `v: 1` in log records. Fwd/bwd compat in `bunyan` CLI

View file

@ -786,8 +786,10 @@ function emitRecord(rec, line, opts, stylize) {
client_req.url, client_req.url,
client_req.httpVersion || "1.1", client_req.httpVersion || "1.1",
hostHeaderLine, hostHeaderLine,
Object.keys(headers).map( (headers
function (h) { return h + ': ' + headers[h]; }).join('\n')); ? Object.keys(headers).map(
function (h) { return h + ': ' + headers[h]; }).join('\n')
: ''));
delete client_req.method; delete client_req.method;
delete client_req.url; delete client_req.url;
delete client_req.httpVersion; delete client_req.httpVersion;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Trent Mick. All rights reserved. * Copyright (c) 2013 Trent Mick. All rights reserved.
* *
* The bunyan logging library for node.js. * The bunyan logging library for node.js.
*/ */
@ -627,26 +627,18 @@ Logger.prototype.levels = function levels(name, value) {
* Pre-condition: This is only called if there is at least one serializer. * Pre-condition: This is only called if there is at least one serializer.
* *
* @param fields (Object) The log record fields. * @param fields (Object) The log record fields.
* @param keys (Array) Optional array of keys to which to limit processing. * @param excludeFields (Object) Optional mapping of keys to `true` for
* keys to NOT apply a serializer.
*/ */
Logger.prototype._applySerializers = function (fields, keys) { Logger.prototype._applySerializers = function (fields, excludeFields) {
var self = this; var self = this;
// Mapping of keys to potentially serialize. xxx('_applySerializers: excludeFields', excludeFields);
var applyKeys = fields;
if (keys) {
applyKeys = {};
for (var i = 0; i < keys.length; i++) {
applyKeys[keys[i]] = true;
}
}
xxx('_applySerializers: applyKeys', applyKeys);
// Check each serializer against these (presuming number of serializers // Check each serializer against these (presuming number of serializers
// is typically less than number of fields). // is typically less than number of fields).
Object.keys(this.serializers).forEach(function (name) { Object.keys(this.serializers).forEach(function (name) {
if (applyKeys[name]) { if (!excludeFields || !excludeFields[name]) {
xxx('_applySerializers; apply to "%s" key', name) xxx('_applySerializers; apply to "%s" key', name)
try { try {
fields[name] = self.serializers[name](fields[name]); fields[name] = self.serializers[name](fields[name]);
@ -732,9 +724,11 @@ function mkLogEmitter(minLevel) {
var log = this; var log = this;
function mkRecord(args) { function mkRecord(args) {
var excludeFields;
if (args[0] instanceof Error) { if (args[0] instanceof Error) {
// `log.<level>(err, ...)` // `log.<level>(err, ...)`
fields = {err: errSerializer(args[0])}; fields = {err: errSerializer(args[0])};
excludeFields = {err: true};
if (args.length === 1) { if (args.length === 1) {
msgArgs = [fields.err.message]; msgArgs = [fields.err.message];
} else { } else {
@ -759,7 +753,7 @@ function mkLogEmitter(minLevel) {
var recFields = (fields ? objCopy(fields) : null); var recFields = (fields ? objCopy(fields) : null);
if (recFields) { if (recFields) {
if (log.serializers) { if (log.serializers) {
log._applySerializers(recFields); log._applySerializers(recFields, excludeFields);
} }
Object.keys(recFields).forEach(function (k) { Object.keys(recFields).forEach(function (k) {
rec[k] = recFields[k]; rec[k] = recFields[k];
@ -885,6 +879,14 @@ function getFullErrorStack(ex)
// Serialize an Error object // Serialize an Error object
// (Core error properties are enumerable in node 0.4, not in 0.6). // (Core error properties are enumerable in node 0.4, not in 0.6).
var errSkips = {
// Skip domain keys. `domain` especially can have huge objects that can
// OOM your app when trying to JSON.stringify.
domain: true,
domain_emitter: true,
domain_bound: true,
domain_thrown: true
};
var errSerializer = Logger.stdSerializers.err = function err(err) { var errSerializer = Logger.stdSerializers.err = function err(err) {
if (!err || !err.stack) if (!err || !err.stack)
return err; return err;
@ -894,7 +896,7 @@ var errSerializer = Logger.stdSerializers.err = function err(err) {
stack: getFullErrorStack(err) stack: getFullErrorStack(err)
} }
Object.keys(err).forEach(function (k) { Object.keys(err).forEach(function (k) {
if (err[k] !== undefined) { if (err[k] !== undefined && !errSkips[k]) {
obj[k] = err[k]; obj[k] = err[k];
} }
}); });

View file

@ -16,11 +16,11 @@
"keywords": ["log", "logging", "log4j", "json"], "keywords": ["log", "logging", "log4j", "json"],
"dependencies": { "dependencies": {
"dtrace-provider": "0.2.7"
}, },
"// comment": "'mv' required for RotatingFileStream", "// comment": "'mv' required for RotatingFileStream",
"optionalDependencies": { "optionalDependencies": {
"mv": "0.0.4" "mv": "0.0.4",
"dtrace-provider": "0.2.8"
}, },
"devDependencies": { "devDependencies": {
"nodeunit": "0.7.4", "nodeunit": "0.7.4",

View file

@ -198,37 +198,37 @@ test('err serializer: long stack', function (t) {
topErr = new verror.VError('top err'); topErr = new verror.VError('top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'Just a VError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'Just a VError');
t.equal(lastRecord.err.stack, topErr.stack); t.equal(lastRecord.err.stack, topErr.stack, 'Just a VError');
// Just a WError. // Just a WError.
topErr = new verror.WError('top err'); topErr = new verror.WError('top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'Just a WError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'Just a WError');
t.equal(lastRecord.err.stack, topErr.stack); t.equal(lastRecord.err.stack, topErr.stack, 'Just a WError');
// WError <- TypeError // WError <- TypeError
bottomErr = new TypeError('bottom err'); bottomErr = new TypeError('bottom err');
topErr = new verror.WError(bottomErr, 'top err'); topErr = new verror.WError(bottomErr, 'top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'WError <- TypeError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'WError <- TypeError');
var expectedStack = topErr.stack + '\nCaused by: ' + bottomErr.stack; var expectedStack = topErr.stack + '\nCaused by: ' + bottomErr.stack;
t.equal(lastRecord.err.stack, expectedStack); t.equal(lastRecord.err.stack, expectedStack, 'WError <- TypeError');
// WError <- WError // WError <- WError
bottomErr = new verror.WError('bottom err'); bottomErr = new verror.WError('bottom err');
topErr = new verror.WError(bottomErr, 'top err'); topErr = new verror.WError(bottomErr, 'top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'WError <- WError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'WError <- WError');
var expectedStack = topErr.stack + '\nCaused by: ' + bottomErr.stack; var expectedStack = topErr.stack + '\nCaused by: ' + bottomErr.stack;
t.equal(lastRecord.err.stack, expectedStack); t.equal(lastRecord.err.stack, expectedStack, 'WError <- WError');
// WError <- WError <- TypeError // WError <- WError <- TypeError
bottomErr = new TypeError('bottom err'); bottomErr = new TypeError('bottom err');
@ -236,12 +236,12 @@ test('err serializer: long stack', function (t) {
topErr = new verror.WError(midErr, 'top err'); topErr = new verror.WError(midErr, 'top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'WError <- WError <- TypeError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'WError <- WError <- TypeError');
var expectedStack = (topErr.stack var expectedStack = (topErr.stack
+ '\nCaused by: ' + midErr.stack + '\nCaused by: ' + midErr.stack
+ '\nCaused by: ' + bottomErr.stack); + '\nCaused by: ' + bottomErr.stack);
t.equal(lastRecord.err.stack, expectedStack); t.equal(lastRecord.err.stack, expectedStack, 'WError <- WError <- TypeError');
// WError <- WError <- WError // WError <- WError <- WError
bottomErr = new verror.WError('bottom err'); bottomErr = new verror.WError('bottom err');
@ -249,12 +249,12 @@ test('err serializer: long stack', function (t) {
topErr = new verror.WError(midErr, 'top err'); topErr = new verror.WError(midErr, 'top err');
log.info(topErr, 'the error'); log.info(topErr, 'the error');
var lastRecord = records[records.length-1]; var lastRecord = records[records.length-1];
t.equal(lastRecord.err.message, topErr.message); t.equal(lastRecord.err.message, topErr.message, 'WError <- WError <- WError');
t.equal(lastRecord.err.name, topErr.name); t.equal(lastRecord.err.name, topErr.name, 'WError <- WError <- WError');
var expectedStack = (topErr.stack var expectedStack = (topErr.stack
+ '\nCaused by: ' + midErr.stack + '\nCaused by: ' + midErr.stack
+ '\nCaused by: ' + bottomErr.stack); + '\nCaused by: ' + bottomErr.stack);
t.equal(lastRecord.err.stack, expectedStack); t.equal(lastRecord.err.stack, expectedStack, 'WError <- WError <- WError');
t.end(); t.end();