[issue #49] Allow a log.child()
to specify the level of inherited streams.
This commit is contained in:
parent
a8279bd90d
commit
677a485348
4 changed files with 152 additions and 17 deletions
10
CHANGES.md
10
CHANGES.md
|
@ -2,6 +2,16 @@
|
||||||
|
|
||||||
## bunyan 0.14.6 (not yet released)
|
## bunyan 0.14.6 (not yet released)
|
||||||
|
|
||||||
|
- [issue #49] Allow a `log.child()` to specify the level of inherited streams.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
# Before
|
||||||
|
var childLog = log.child({...});
|
||||||
|
childLog.level('debug');
|
||||||
|
|
||||||
|
# After
|
||||||
|
var childLog = log.child({..., level: 'debug'});
|
||||||
|
|
||||||
- Improve the crash message to make it easier to provide relevant details in a
|
- Improve the crash message to make it easier to provide relevant details in a
|
||||||
bug report.
|
bug report.
|
||||||
|
|
||||||
|
|
|
@ -238,9 +238,8 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
throw new TypeError('invalid options.name: child cannot set logger name');
|
throw new TypeError('invalid options.name: child cannot set logger name');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((options.stream || options.level) && options.streams) {
|
if (options.stream && options.streams) {
|
||||||
throw new TypeError(
|
throw new TypeError('cannot mix "streams" and "stream" options');
|
||||||
'cannot mix "streams" with "stream" or "level" options');
|
|
||||||
}
|
}
|
||||||
if (options.streams && !Array.isArray(options.streams)) {
|
if (options.streams && !Array.isArray(options.streams)) {
|
||||||
throw new TypeError('invalid options.streams: must be an array')
|
throw new TypeError('invalid options.streams: must be an array')
|
||||||
|
@ -289,6 +288,9 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
this.serializers = objCopy(parent.serializers);
|
this.serializers = objCopy(parent.serializers);
|
||||||
this.src = parent.src;
|
this.src = parent.src;
|
||||||
this.fields = objCopy(parent.fields);
|
this.fields = objCopy(parent.fields);
|
||||||
|
if (options.level) {
|
||||||
|
this.level(options.level);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._level = Number.POSITIVE_INFINITY;
|
this._level = Number.POSITIVE_INFINITY;
|
||||||
this.streams = [];
|
this.streams = [];
|
||||||
|
@ -314,6 +316,8 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
|
|
||||||
if (s.level) {
|
if (s.level) {
|
||||||
s.level = resolveLevel(s.level);
|
s.level = resolveLevel(s.level);
|
||||||
|
} else if (options.level) {
|
||||||
|
s.level = resolveLevel(options.level);
|
||||||
} else {
|
} else {
|
||||||
s.level = INFO;
|
s.level = INFO;
|
||||||
}
|
}
|
||||||
|
@ -370,7 +374,8 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle *config* options.
|
// Handle *config* options (i.e. options that are not just plain data
|
||||||
|
// for log records).
|
||||||
if (options.stream) {
|
if (options.stream) {
|
||||||
addStream({
|
addStream({
|
||||||
type: 'stream',
|
type: 'stream',
|
||||||
|
@ -380,6 +385,8 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
});
|
});
|
||||||
} else if (options.streams) {
|
} else if (options.streams) {
|
||||||
options.streams.forEach(addStream);
|
options.streams.forEach(addStream);
|
||||||
|
} else if (parent && options.level) {
|
||||||
|
this.level(options.level);
|
||||||
} else if (!parent) {
|
} else if (!parent) {
|
||||||
addStream({
|
addStream({
|
||||||
type: 'stream',
|
type: 'stream',
|
||||||
|
@ -439,9 +446,12 @@ util.inherits(Logger, EventEmitter);
|
||||||
* @param options {Object} Optional. Set of options to apply to the child.
|
* @param options {Object} Optional. Set of options to apply to the child.
|
||||||
* All of the same options for a new Logger apply here. Notes:
|
* All of the same options for a new Logger apply here. Notes:
|
||||||
* - The parent's streams are inherited and cannot be removed in this
|
* - The parent's streams are inherited and cannot be removed in this
|
||||||
* call.
|
* call. Any given `streams` are *added* to the set inherited from
|
||||||
|
* the parent.
|
||||||
* - The parent's serializers are inherited, though can effectively be
|
* - The parent's serializers are inherited, though can effectively be
|
||||||
* overwritten by using duplicate keys.
|
* overwritten by using duplicate keys.
|
||||||
|
* - Can use `level` to set the level of the streams inherited from
|
||||||
|
* the parent. The level for the parent is NOT affected.
|
||||||
* @param simple {Boolean} Optional. Set to true to assert that `options`
|
* @param simple {Boolean} Optional. Set to true to assert that `options`
|
||||||
* (a) only add fields (no config) and (b) no serialization handling is
|
* (a) only add fields (no config) and (b) no serialization handling is
|
||||||
* required for them. IOW, this is a fast path for frequent child
|
* required for them. IOW, this is a fast path for frequent child
|
||||||
|
|
127
test/child-behaviour.test.js
Normal file
127
test/child-behaviour.test.js
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Trent Mick. All rights reserved.
|
||||||
|
*
|
||||||
|
* Test some `<Logger>.child(...)` behaviour.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var test = require('tap').test;
|
||||||
|
var bunyan = require('../lib/bunyan');
|
||||||
|
|
||||||
|
function CapturingStream(recs) {
|
||||||
|
this.recs = recs || [];
|
||||||
|
}
|
||||||
|
CapturingStream.prototype.write = function (rec) {
|
||||||
|
this.recs.push(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test('child can add stream', function (t) {
|
||||||
|
var dadStream = new CapturingStream();
|
||||||
|
var dad = bunyan.createLogger({
|
||||||
|
name: 'surname',
|
||||||
|
streams: [{
|
||||||
|
type: 'raw',
|
||||||
|
stream: dadStream,
|
||||||
|
level: 'info'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
var sonStream = new CapturingStream();
|
||||||
|
var son = dad.child({
|
||||||
|
component: 'son',
|
||||||
|
streams: [{
|
||||||
|
type: 'raw',
|
||||||
|
stream: sonStream,
|
||||||
|
level: 'debug'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
dad.info('info from dad');
|
||||||
|
dad.debug('debug from dad');
|
||||||
|
son.debug('debug from son');
|
||||||
|
|
||||||
|
var rec;
|
||||||
|
t.equal(dadStream.recs.length, 1);
|
||||||
|
rec = dadStream.recs[0];
|
||||||
|
t.equal(rec.msg, 'info from dad');
|
||||||
|
t.equal(sonStream.recs.length, 1);
|
||||||
|
rec = sonStream.recs[0];
|
||||||
|
t.equal(rec.msg, 'debug from son');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('child can set level of inherited streams', function (t) {
|
||||||
|
var dadStream = new CapturingStream();
|
||||||
|
var dad = bunyan.createLogger({
|
||||||
|
name: 'surname',
|
||||||
|
streams: [{
|
||||||
|
type: 'raw',
|
||||||
|
stream: dadStream,
|
||||||
|
level: 'info'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intention here is that the inherited `dadStream` logs at 'debug' level
|
||||||
|
// for the son.
|
||||||
|
var son = dad.child({
|
||||||
|
component: 'son',
|
||||||
|
level: 'debug'
|
||||||
|
});
|
||||||
|
|
||||||
|
dad.info('info from dad');
|
||||||
|
dad.debug('debug from dad');
|
||||||
|
son.debug('debug from son');
|
||||||
|
|
||||||
|
var rec;
|
||||||
|
t.equal(dadStream.recs.length, 2);
|
||||||
|
rec = dadStream.recs[0];
|
||||||
|
t.equal(rec.msg, 'info from dad');
|
||||||
|
rec = dadStream.recs[1];
|
||||||
|
t.equal(rec.msg, 'debug from son');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('child can set level of inherited streams and add streams', function (t) {
|
||||||
|
var dadStream = new CapturingStream();
|
||||||
|
var dad = bunyan.createLogger({
|
||||||
|
name: 'surname',
|
||||||
|
streams: [{
|
||||||
|
type: 'raw',
|
||||||
|
stream: dadStream,
|
||||||
|
level: 'info'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intention here is that the inherited `dadStream` logs at 'debug' level
|
||||||
|
// for the son.
|
||||||
|
var sonStream = new CapturingStream();
|
||||||
|
var son = dad.child({
|
||||||
|
component: 'son',
|
||||||
|
level: 'trace',
|
||||||
|
streams: [{
|
||||||
|
type: 'raw',
|
||||||
|
stream: sonStream,
|
||||||
|
level: 'debug'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
dad.info('info from dad');
|
||||||
|
dad.trace('trace from dad');
|
||||||
|
son.trace('trace from son');
|
||||||
|
son.debug('debug from son');
|
||||||
|
|
||||||
|
t.equal(dadStream.recs.length, 3);
|
||||||
|
t.equal(dadStream.recs[0].msg, 'info from dad');
|
||||||
|
t.equal(dadStream.recs[1].msg, 'trace from son');
|
||||||
|
t.equal(dadStream.recs[2].msg, 'debug from son');
|
||||||
|
|
||||||
|
t.equal(sonStream.recs.length, 1);
|
||||||
|
t.equal(sonStream.recs[0].msg, 'debug from son');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
|
@ -26,10 +26,6 @@ test('ensure Logger creation options', function (t) {
|
||||||
t.throws(function () { new Logger(options); },
|
t.throws(function () { new Logger(options); },
|
||||||
'cannot use "stream" and "streams"');
|
'cannot use "stream" and "streams"');
|
||||||
|
|
||||||
options = {name: 'foo', level: 'info', streams: []};
|
|
||||||
t.throws(function () { new Logger(options); },
|
|
||||||
'cannot use "level" and "streams"');
|
|
||||||
|
|
||||||
// https://github.com/trentm/node-bunyan/issues/3
|
// https://github.com/trentm/node-bunyan/issues/3
|
||||||
options = {name: 'foo', streams: {}};
|
options = {name: 'foo', streams: {}};
|
||||||
t.throws(function () { new Logger(options); },
|
t.throws(function () { new Logger(options); },
|
||||||
|
@ -72,10 +68,6 @@ test('ensure Logger creation options (createLogger)', function (t) {
|
||||||
t.throws(function () { bunyan.createLogger(options); },
|
t.throws(function () { bunyan.createLogger(options); },
|
||||||
'cannot use "stream" and "streams"');
|
'cannot use "stream" and "streams"');
|
||||||
|
|
||||||
options = {name: 'foo', level: 'info', streams: []};
|
|
||||||
t.throws(function () { bunyan.createLogger(options); },
|
|
||||||
'cannot use "level" and "streams"');
|
|
||||||
|
|
||||||
// https://github.com/trentm/node-bunyan/issues/3
|
// https://github.com/trentm/node-bunyan/issues/3
|
||||||
options = {name: 'foo', streams: {}};
|
options = {name: 'foo', streams: {}};
|
||||||
t.throws(function () { bunyan.createLogger(options); },
|
t.throws(function () { bunyan.createLogger(options); },
|
||||||
|
@ -122,10 +114,6 @@ test('ensure Logger child() options', function (t) {
|
||||||
t.throws(function () { log.child(options); },
|
t.throws(function () { log.child(options); },
|
||||||
'cannot use "stream" and "streams"');
|
'cannot use "stream" and "streams"');
|
||||||
|
|
||||||
options = {level: 'info', streams: []};
|
|
||||||
t.throws(function () { log.child(options); },
|
|
||||||
'cannot use "level" and "streams"');
|
|
||||||
|
|
||||||
// https://github.com/trentm/node-bunyan/issues/3
|
// https://github.com/trentm/node-bunyan/issues/3
|
||||||
options = {streams: {}};
|
options = {streams: {}};
|
||||||
t.throws(function () { log.child(options); },
|
t.throws(function () { log.child(options); },
|
||||||
|
|
Loading…
Reference in a new issue