[issue #85] Ensure logging a non-object/non-string doesn't throw

This commit is contained in:
Trent Mick 2014-05-28 23:24:57 -07:00
parent 7b08dd607d
commit fc0150f9fb
7 changed files with 206 additions and 23 deletions

View file

@ -5,3 +5,4 @@ Michael Hart (https://github.com/mhart)
Isaac Schlueter (https://github.com/isaacs) Isaac Schlueter (https://github.com/isaacs)
Rob Gulewich (https://github.com/rgulewich) Rob Gulewich (https://github.com/rgulewich)
Bryan Cantrill (https://github.com/bcantrill) Bryan Cantrill (https://github.com/bcantrill)
Michael Hart (https://github.com/mhart)

View file

@ -6,9 +6,17 @@ Known issues:
bug](https://github.com/TooTallNate/node-gyp/issues/65). bug](https://github.com/TooTallNate/node-gyp/issues/65).
## bunyan 0.22.4 (not yet released) ## bunyan 0.23.0 (not yet released)
(nothing yet) - Drop node 0.6 support. I can't effectively `npm install` with a node 0.6
anymore.
- [issue #85] Ensure logging a non-object/non-string doesn't throw (by
https://github.com/mhart). This changes fixes:
log.info(<bool>) # TypeError: Object.keys called on non-object
log.info(<function>) # "msg":"" (instead of wanted "msg":"[Function]")
log.info(<array>) # "msg":"" (instead of wanted "msg":util.format(<array>))
## bunyan 0.22.3 ## bunyan 0.22.3
@ -20,28 +28,28 @@ Known issues:
Note: Bad release. The published package in the npm registry got corrupted. Use 0.22.3 or later. Note: Bad release. The published package in the npm registry got corrupted. Use 0.22.3 or later.
- #131 Allow `log.info(<number>)` and, most importantly, don't crash on that. - [issue #131] Allow `log.info(<number>)` and, most importantly, don't crash on that.
- Update 'mv' optional dep to latest. - Update 'mv' optional dep to latest.
## bunyan 0.22.1 ## bunyan 0.22.1
- #111 Fix a crash when attempting to use `bunyan -p` on a platform without - [issue #111] Fix a crash when attempting to use `bunyan -p` on a platform without
dtrace. dtrace.
- #101 Fix a crash in `bunyan` rendering a record with unexpected "res.headers". - [issue #101] Fix a crash in `bunyan` rendering a record with unexpected "res.headers".
## bunyan 0.22.0 ## bunyan 0.22.0
- #104 `log.reopenFileStreams()` convenience method to be used with external log - [issue #104] `log.reopenFileStreams()` convenience method to be used with external log
rotation. rotation.
## bunyan 0.21.4 ## bunyan 0.21.4
- #96 Fix `bunyan` to default to paging (with `less`) by default in node 0.10.0. - [issue #96] Fix `bunyan` to default to paging (with `less`) by default in node 0.10.0.
The intention has always been to default to paging for node >=0.8. The intention has always been to default to paging for node >=0.8.

View file

@ -82,10 +82,10 @@ test: $(NODEUNIT)
# Test will all node supported versions (presumes install locations I use on # Test will all node supported versions (presumes install locations I use on
# my machine). # my machine).
# Note: 'test08' is last so (if all is well) I end up with a binary # Note: 'test10' is last so (if all is well) I end up with a binary
# dtrace-provider build for node 0.8 (my current version). # dtrace-provider build for node 0.10 (my current version).
.PHONY: testall .PHONY: testall
testall: test06 test10 test08 testall: test08 test10
.PHONY: test10 .PHONY: test10
test10: test10:
@ -97,11 +97,6 @@ test08:
@echo "# Test node 0.8.x (with node `$(NODEOPT)/node-0.8/bin/node --version`)" @echo "# Test node 0.8.x (with node `$(NODEOPT)/node-0.8/bin/node --version`)"
@$(NODEOPT)/node-0.8/bin/node --version @$(NODEOPT)/node-0.8/bin/node --version
PATH="$(NODEOPT)/node-0.8/bin:$(PATH)" make distclean all test PATH="$(NODEOPT)/node-0.8/bin:$(PATH)" make distclean all test
.PHONY: test06
test06:
@echo "# Test node 0.6.x (with node `$(NODEOPT)/node-0.6/bin/node --version`)"
@$(NODEOPT)/node-0.6/bin/node --version
PATH="$(NODEOPT)/node-0.6/bin:$(PATH)" make distclean all test
#---- check #---- check

View file

@ -6,7 +6,7 @@
// See <https://github.com/trentm/node-bunyan>. // See <https://github.com/trentm/node-bunyan>.
// //
var VERSION = '0.22.4'; var VERSION = '0.23.0';
var p = console.log; var p = console.log;
var util = require('util'); var util = require('util');

View file

@ -7,7 +7,7 @@
* vim: expandtab:ts=4:sw=4 * vim: expandtab:ts=4:sw=4
*/ */
var VERSION = '0.22.4'; var VERSION = '0.23.0';
// Bunyan log format version. This becomes the 'v' field on all log records. // Bunyan log format version. This becomes the 'v' field on all log records.
// `0` is until I release a version '1.0.0' of node-bunyan. Thereafter, // `0` is until I release a version '1.0.0' of node-bunyan. Thereafter,
@ -769,8 +769,8 @@ function mkLogEmitter(minLevel) {
} else { } else {
msgArgs = Array.prototype.slice.call(args, 1); msgArgs = Array.prototype.slice.call(args, 1);
} }
} else if (typeof (args[0]) === 'string' || } else if (typeof (args[0]) !== 'object' && args[0] !== null ||
typeof (args[0]) === 'number') { Array.isArray(args[0])) {
// `log.<level>(msg, ...)` // `log.<level>(msg, ...)`
fields = null; fields = null;
msgArgs = Array.prototype.slice.call(args); msgArgs = Array.prototype.slice.call(args);

View file

@ -1,6 +1,6 @@
{ {
"name": "bunyan", "name": "bunyan",
"version": "0.22.4", "version": "0.23.0",
"description": "a JSON Logger library for node.js services", "description": "a JSON Logger library for node.js services",
"author": "Trent Mick <trentm@gmail.com> (http://trentm.com)", "author": "Trent Mick <trentm@gmail.com> (http://trentm.com)",
"main": "./lib/bunyan.js", "main": "./lib/bunyan.js",
@ -12,7 +12,7 @@
"type": "git", "type": "git",
"url": "git://github.com/trentm/node-bunyan.git" "url": "git://github.com/trentm/node-bunyan.git"
}, },
"engines": ["node >=0.6.0"], "engines": ["node >=0.8.0"],
"keywords": ["log", "logging", "log4j", "json"], "keywords": ["log", "logging", "log4j", "json"],
"dependencies": { "dependencies": {

View file

@ -4,6 +4,11 @@
* Test the `log.trace(...)`, `log.debug(...)`, ..., `log.fatal(...)` API. * Test the `log.trace(...)`, `log.debug(...)`, ..., `log.fatal(...)` API.
*/ */
var util = require('util'),
format = util.format,
inspect = util.inspect;
var p = console.log;
var bunyan = require('../lib/bunyan'); var bunyan = require('../lib/bunyan');
// node-tap API // node-tap API
@ -15,6 +20,8 @@ var before = tap4nodeunit.before;
var test = tap4nodeunit.test; var test = tap4nodeunit.test;
// ---- test boolean `log.<level>()` calls
var log1 = bunyan.createLogger({ var log1 = bunyan.createLogger({
name: 'log1', name: 'log1',
streams: [ streams: [
@ -57,5 +64,177 @@ test('log.LEVEL() -> boolean', function (t) {
t.end(); t.end();
}); });
//TODO:
// - rest of api // ---- test `log.<level>(...)` calls which various input types
function Catcher() {
this.records = [];
}
Catcher.prototype.write = function (record) {
this.records.push(record);
}
var catcher = new Catcher();
var log3 = new bunyan.createLogger({
name: 'log3',
streams: [
{
type: 'raw',
stream: catcher,
level: 'trace'
}
]
});
var names = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
var fields = {one: 'un'};
test('log.info(undefined, <msg>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, undefined, 'some message');
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'undefined \'some message\'',
format('log.%s msg is "some message"', lvl));
});
t.end();
});
test('log.info(<fields>, undefined)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, undefined);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'undefined',
format('log.%s msg: expect "undefined", got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(null, <msg>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, null, 'some message');
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'some message',
format('log.%s msg is "some message"', lvl));
});
t.end();
});
test('log.info(<fields>, null)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, null);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'null',
format('log.%s msg: expect "null", got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(<str>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, 'some message');
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'some message',
format('log.%s msg is "some message"', lvl));
});
t.end();
});
test('log.info(<fields>, <str>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, 'some message');
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'some message',
format('log.%s msg: got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(<bool>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, true);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'true',
format('log.%s msg is "true"', lvl));
});
t.end();
});
test('log.info(<fields>, <bool>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, true);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, 'true',
format('log.%s msg: got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(<num>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, 3.14);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, '3.14',
format('log.%s msg: got %j', lvl, rec.msg));
});
t.end();
});
test('log.info(<fields>, <num>)', function (t) {
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, 3.14);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, '3.14',
format('log.%s msg: got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(<function>)', function (t) {
var func = function func1() {};
names.forEach(function (lvl) {
log3[lvl].call(log3, func);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, '[Function: func1]',
format('log.%s msg: got %j', lvl, rec.msg));
});
t.end();
});
test('log.info(<fields>, <function>)', function (t) {
var func = function func2() {};
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, func);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, '[Function: func2]',
format('log.%s msg: got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});
test('log.info(<array>)', function (t) {
var arr = ['a', 1, {two: 'deux'}];
names.forEach(function (lvl) {
log3[lvl].call(log3, arr);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, format(arr),
format('log.%s msg: got %j', lvl, rec.msg));
});
t.end();
});
test('log.info(<fields>, <array>)', function (t) {
var arr = ['a', 1, {two: 'deux'}];
names.forEach(function (lvl) {
log3[lvl].call(log3, fields, arr);
var rec = catcher.records[catcher.records.length - 1];
t.equal(rec.msg, format(arr),
format('log.%s msg: got %j', lvl, rec.msg));
t.equal(rec.one, 'un');
});
t.end();
});