Add log.level(...) and log.levels(...) API for changing logger stream levels.

This commit is contained in:
Trent Mick 2012-02-06 15:04:47 -08:00
parent 632c044ad3
commit 352c4177b7
5 changed files with 181 additions and 16 deletions

View file

@ -2,6 +2,9 @@
## bunyan 0.5.0 (not yet released) ## bunyan 0.5.0 (not yet released)
- Add `log.level(...)` and `log.levels(...)` API for changing logger stream
levels.
- Add `TRACE|DEBUG|INFO|WARN|ERROR|FATAL` level constants to exports.
- Add `log.info(err)` special case for logging an `Error` instance. For - Add `log.info(err)` special case for logging an `Error` instance. For
example `log.info(new TypeError("boom")` will produce: example `log.info(new TypeError("boom")` will produce:

View file

@ -220,6 +220,22 @@ Integers are used for the actual level values (1 for "trace", ..., 6 for
"fatal") and constants are defined for the (Logger.TRACE ... Logger.DEBUG). "fatal") and constants are defined for the (Logger.TRACE ... Logger.DEBUG).
The lowercase level names are aliases supported in the API. The lowercase level names are aliases supported in the API.
Here is the API for changing levels in an existing logger:
log.level() -> INFO // gets current level (lowest level of all streams)
log.level(INFO) // set all streams to level INFO
log.level("info") // set all streams to level INFO
log.levels() -> [DEBUG, INFO] // get array of levels of all streams
log.levels(0) -> DEBUG // get level of stream at index 0
log.levels("foo") // get level of stream with name "foo"
log.levels(0, INFO) // set level of stream 0 to INFO
log.levels(0, "info") // can use "info" et al aliases
log.levels("foo", WARN) // set stream named "foo" to WARN
# Log Record Fields # Log Record Fields

View file

@ -1,8 +1,8 @@
- line/file: possible to get quickly with v8? Yunong asked.
file/line/func (?)
- Logger.setLevel()? How to change level for a given stream. Default all, - Logger.setLevel()? How to change level for a given stream. Default all,
else, give an index... or type ... or support stream "names". Some positives else, give an index... or type ... or support stream "names". Some positives
to stream names. to stream names.
- service -> name
- 10, 20,...
- bunyan cli: more layouts (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html) - bunyan cli: more layouts (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html)
Custom log formats (in config file? in '-f' arg) using printf or hogan.js Custom log formats (in config file? in '-f' arg) using printf or hogan.js
or whatever. Dap wants field width control for lining up. Hogan.js is or whatever. Dap wants field width control for lining up. Hogan.js is

47
examples/level.js Normal file
View file

@ -0,0 +1,47 @@
// Play with setting levels.
//
// TODO: put this in a damn test suite
var Logger = require('../lib/bunyan'),
DEBUG = Logger.DEBUG,
INFO = Logger.INFO,
WARN = Logger.WARN;
var assert = require('assert');
// Basic usage.
var log = new Logger({
service: 'example-level',
streams: [
{
name: 'stdout',
stream: process.stdout,
level: 'debug'
},
{
name: 'stderr',
stream: process.stderr
}
]
});
assert.equal(log.level(), DEBUG);
assert.equal(log.levels()[0], DEBUG);
assert.equal(log.levels()[1], INFO);
assert.equal(log.levels(0), DEBUG);
assert.equal(log.levels(1), INFO);
assert.equal(log.levels('stdout'), DEBUG)
try {
log.levels('foo')
} catch (e) {
assert.ok(e.message.indexOf('name') !== -1)
}
log.trace("no one should see this")
log.debug("should see this once (on stdout)")
log.info("should see this twice")
log.levels('stdout', INFO)
log.debug("no one should see this either")
log.level('trace')
log.trace('should see this twice as 4th and 5th emitted log messages')

View file

@ -22,6 +22,7 @@ var xxx = function xxx() {}; // uncomment to turn of debug logging
var os = require('os'); var os = require('os');
var fs = require('fs'); var fs = require('fs');
var util = require('util'); var util = require('util');
var assert = require('assert');
@ -201,7 +202,7 @@ function Logger(options, _childOptions, _childSimple) {
// streams. // streams.
this._isSimpleChild = true; this._isSimpleChild = true;
this.level = parent.level; this._level = parent._level;
this.streams = parent.streams; this.streams = parent.streams;
this.serializers = parent.serializers; this.serializers = parent.serializers;
this.src = parent.src; this.src = parent.src;
@ -217,7 +218,7 @@ function Logger(options, _childOptions, _childSimple) {
// Null values. // Null values.
var self = this; var self = this;
if (parent) { if (parent) {
this.level = parent.level; this._level = parent._level;
this.streams = []; this.streams = [];
for (var i = 0; i < parent.streams.length; i++) { for (var i = 0; i < parent.streams.length; i++) {
var s = objCopy(parent.streams[i]); var s = objCopy(parent.streams[i]);
@ -228,7 +229,7 @@ function Logger(options, _childOptions, _childSimple) {
this.src = parent.src; this.src = parent.src;
this.fields = objCopy(parent.fields); this.fields = objCopy(parent.fields);
} else { } else {
this.level = Number.POSITIVE_INFINITY; this._level = Number.POSITIVE_INFINITY;
this.streams = []; this.streams = [];
this.serializers = null; this.serializers = null;
this.src = false; this.src = false;
@ -254,8 +255,8 @@ function Logger(options, _childOptions, _childSimple) {
} else { } else {
s.level = INFO; s.level = INFO;
} }
if (s.level < self.level) { if (s.level < self._level) {
self.level = s.level; self._level = s.level;
} }
switch (s.type) { switch (s.type) {
@ -399,6 +400,98 @@ Logger.prototype.child = function (options, simple) {
//} //}
/**
* Get/set the level of all streams on this logger.
*
* Get Usage:
* // Returns the current log level (lowest level of all its streams).
* log.level() -> INFO
*
* Set Usage:
* log.level(INFO) // set all streams to level INFO
* log.level("info") // can use "info" et al aliases
*/
Logger.prototype.level = function level(value) {
if (value === undefined) {
return this._level;
}
var newLevel = resolveLevel(value);
var len = this.streams.length;
for (var i = 0; i < len; i++) {
this.streams[i].level = newLevel;
}
this._level = newLevel;
}
/**
* Get/set the level of a particular stream on this logger.
*
* Get Usage:
* // Returns an array of the levels of each stream.
* log.levels() -> [TRACE, INFO]
*
* // Returns a level of the identified stream.
* log.levels(0) -> TRACE // level of stream at index 0
* log.levels("foo") // level of stream with name "foo"
*
* Set Usage:
* log.levels(0, INFO) // set level of stream 0 to INFO
* log.levels(0, "info") // can use "info" et al aliases
* log.levels("foo", WARN) // set stream named "foo" to WARN
*
* Stream names: When streams are defined, they can optionally be given
* a name. For example,
* log = new Logger({
* streams: [
* {
* name: 'foo', // <--- proposed new option, yucky controlling uniqueness
* path: '/var/log/my-service/foo.log'
* level: 'trace'
* },
* ...
*
* @param name {String|Number} The stream index or name.
* @param value {Number|String} The level value (INFO) or alias ("info").
* If not given, this is a 'get' operation.
* @throws {Error} If there is no stream with the given name.
*/
Logger.prototype.levels = function levels(name, value) {
if (name === undefined) {
assert.equal(value, undefined);
return this.streams.map(function (s) { return s.level });
}
var stream;
if (typeof name === 'number') {
stream = this.streams[name];
if (stream === undefined) {
throw new Error('invalid stream index: ' + name);
}
} else {
var len = this.streams.length;
for (var i = 0; i < len; i++) {
var s = this.streams[i];
if (s.name === name) {
stream = s;
break;
}
}
if (!stream) {
throw new Error(format('no stream with name "%s"', name));
}
}
if (value === undefined) {
return stream.level;
} else {
var newLevel = resolveLevel(value);
stream.level = newLevel;
if (newLevel < this._level) {
this._level = newLevel;
}
}
}
/** /**
* Apply registered serializers to the appropriate keys in the given fields. * Apply registered serializers to the appropriate keys in the given fields.
* *
@ -760,7 +853,13 @@ var errSerializer = Logger.stdSerializers.err = function err(err) {
//---- Exports //---- Exports
module.exports = Logger; module.exports = Logger;
module.exports.TRACE = TRACE;
module.exports.DEBUG = DEBUG;
module.exports.INFO = INFO;
module.exports.WARN = WARN;
module.exports.ERROR = ERROR;
module.exports.FATAL = FATAL;
module.exports.VERSION = VERSION; module.exports.VERSION = VERSION;
module.exports.LOG_VERSION = LOG_VERSION; module.exports.LOG_VERSION = LOG_VERSION;