diff --git a/AUTHORS b/AUTHORS index 6dbdd94..87df086 100644 --- a/AUTHORS +++ b/AUTHORS @@ -25,3 +25,4 @@ Shakeel Mohamed (https://github.com/shakeelmohamed) Denis Izmaylov (https://github.com/DenisIzmaylov) Guillermo Grau Panea (https://github.com/guigrpa) Mark LeMerise (https://github.com/MarkLeMerise) +https://github.com/sometimesalready diff --git a/CHANGES.md b/CHANGES.md index 5111e9a..9178fe8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,12 @@ Known issues: ## 1.5.2 (not yet released) -(nothing yet) +- [issue #325] Allow one to set `level: 0` in `createLogger` to turn on + logging for all levels. (Adapted from #336 by github.com/sometimesalready.) + +- Add guards (to `resolveLevel`) so that all "level" values are validated. + Before this, a bogus level like "foo" or -12 or `['some', 'array']` would + silently be accepted -- with undefined results. ## 1.5.1 diff --git a/lib/bunyan.js b/lib/bunyan.js index 97d2d47..bda7006 100644 --- a/lib/bunyan.js +++ b/lib/bunyan.js @@ -248,12 +248,27 @@ var probes = dtrace && {}; /** * Resolve a level number, name (upper or lowercase) to a level number value. * + * @param nameOrNum {String|Number} A level name (case-insensitive) or positive + * integer level. * @api public */ function resolveLevel(nameOrNum) { - var level = (typeof (nameOrNum) === 'string' - ? levelFromName[nameOrNum.toLowerCase()] - : nameOrNum); + var level; + var type = typeof (nameOrNum); + if (type === 'string') { + level = levelFromName[nameOrNum.toLowerCase()]; + if (!level) { + throw new Error(format('unknown level name: "%s"', nameOrNum)); + } + } else if (type !== 'number') { + throw new TypeError(format('cannot resolve level: invalid arg (%s):', + type, nameOrNum)); + } else if (nameOrNum < 0 || Math.floor(nameOrNum) !== nameOrNum) { + throw new TypeError(format('level is not a positive integer: %s', + nameOrNum)); + } else { + level = nameOrNum; + } return level; } @@ -513,7 +528,7 @@ Logger.prototype.addStream = function addStream(s, defaultLevel) { } s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`. - if (s.level) { + if (s.level !== undefined) { s.level = resolveLevel(s.level); } else { s.level = resolveLevel(defaultLevel); diff --git a/test/level.test.js b/test/level.test.js index 7e6a33f..ab619f2 100644 --- a/test/level.test.js +++ b/test/level.test.js @@ -69,5 +69,30 @@ test('log.level()', function (t) { t.equal(log1.level(), 0); log1.level(Number.MAX_VALUE); t.equal(log1.level(), Number.MAX_VALUE); + log1.level(Infinity); + t.equal(log1.level(), Infinity); + t.end(); +}); + +test('log.level()', function (t) { + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: 'booga'}); + // JSSTYLED + }, /unknown level name: "booga"/); + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: []}); + }, /cannot resolve level: invalid arg \(object\): \[\]/); + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: true}); + }, /cannot resolve level: invalid arg \(boolean\): true/); + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: -1}); + }, /level is not a positive integer: -1/); + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: 3.14}); + }, /level is not a positive integer: 3.14/); + t.throws(function () { + var log = bunyan.createLogger({name: 'invalid', level: -Infinity}); + }, /level is not a positive integer: -Infinity/); t.end(); }); diff --git a/test/stream-levels.test.js b/test/stream-levels.test.js index 7e2969d..6e12e09 100644 --- a/test/stream-levels.test.js +++ b/test/stream-levels.test.js @@ -171,3 +171,14 @@ test('two streams, one with "level" specified', function (t) { t.equal(log.streams[1].level, bunyan.FATAL); t.end(); }); + +// Issue #335 +test('log level 0 to turn on all logging', function (t) { + var log = bunyan.createLogger({ + name: 'foo', + level: 0 + }); + t.equal(log.level(), 0); + t.equal(log.streams[0].level, 0); + t.end(); +});