diff --git a/CHANGES.md b/CHANGES.md index 111dfc9..2bb44e7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,19 @@ # bunyan Changelog -## bunyan 0.4.1 (not yet released) +## bunyan 0.5.0 (not yet released) + +- Add `log.info(err)` special case for logging an `Error` instance. For + example `log.info(new TypeError("boom")` will produce: + + ... + "err": { + "message": "boom", + "name": "TypeError", + "stack": "TypeError: boom\n at Object. ..." + }, + "msg": "boom", + ... -(nothing yet) ## bunyan 0.4.0 diff --git a/README.md b/README.md index 3de03bf..3190a49 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,13 @@ format version) are added for you. The full `log.{trace|debug|...|fatal}(...)` API is: - log.info(); // returns a boolean: is the "info" level enabled? - log.info("hi"); // log a simple string message - log.info("hi %s", bob, anotherVar); // uses `util.format` for msg formatting - log.info({foo: "bar"}, "hi"); // adds "foo" field to log record + log.info(); // Returns a boolean: is the "info" level enabled? + log.info(err); // Log an `Error` instance, adds "err" key with exception details + // (including the stack) and sets "msg" to the exception message. + // A special case, b/c logging errors should be easy. + log.info("hi"); // Log a simple string message. + log.info("hi %s", bob, anotherVar); // Uses `util.format` for msg formatting. + log.info({foo: "bar"}, "hi"); // Adds "foo" field to log record. ## bunyan tool @@ -293,9 +296,21 @@ follow (feedback from actual users welcome). Recommended/Best Practice Fields: -- `err`: Object. A caught JS exception. Log that thing with - `log.error({err: err}, "oops")` and **use the `Logger.stdSerializers.err`** - serializer for it. See "examples/err.js". +- `err`: Object. A caught JS exception. Log that thing with `log.info(err)` + to get: + + ... + "err": { + "message": "boom", + "name": "TypeError", + "stack": "TypeError: boom\n at Object. ..." + }, + "msg": "boom", + ... + + Or use the `Logger.stdSerializers.err` serializer in your Logger and + do this `log.error({err: err}, "oops")`. See "examples/err.js". + - `req_id`: String. A request identifier. Including this field in all logging tied to handling a particular request to your server is strongly suggested. This allows post analysis of logs to easily collate all related logging @@ -303,6 +318,7 @@ Recommended/Best Practice Fields: and you carry a single request ID from the top API down through all APIs (as [node-restify](https://github.com/mcavage/node-restify) facilitates with its 'X-Request-Id' header). + - `req`: An HTTP server request. Bunyan provides `Logger.stdSerializers.req` to serialize a request with a suggested set of keys. Example: diff --git a/bin/bunyan b/bin/bunyan index f1c1da2..16de1d6 100755 --- a/bin/bunyan +++ b/bin/bunyan @@ -5,7 +5,7 @@ // See . // -var VERSION = "0.4.1"; +var VERSION = "0.5.0"; var util = require('util'); var pathlib = require('path'); diff --git a/examples/err.js b/examples/err.js index b9973cc..8a9caae 100644 --- a/examples/err.js +++ b/examples/err.js @@ -17,6 +17,15 @@ try { log.warn({err: err}, "operation went boom: %s", err) // <--- here } +log.info(new TypeError("how about this?")) // <--- alternatively this + + +try { + throw "boom string"; +} catch (err) { + log.error(err) +} + /* $ node err.js | ../bin/bunyan -j diff --git a/lib/bunyan.js b/lib/bunyan.js index 0e057bd..02d56e2 100644 --- a/lib/bunyan.js +++ b/lib/bunyan.js @@ -2,7 +2,7 @@ * Copyright 2012 (c) Trent Mick. All rights reserved. */ -var VERSION = "0.4.1"; +var VERSION = "0.5.0"; // 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, @@ -501,6 +501,7 @@ Logger.prototype._emit = function (rec) { * * Usages: * log.trace() -> boolean is-trace-enabled + * log.trace( err) * log.trace( msg, ...) * log.trace( fields, msg, ...) * @@ -515,6 +516,10 @@ Logger.prototype.trace = function () { return (this.level <= TRACE); } else if (this.level > TRACE) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.trace(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.trace(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -531,6 +536,7 @@ Logger.prototype.trace = function () { * * Usages: * log.debug() -> boolean is-debug-enabled + * log.debug( err) * log.debug( msg, ...) * log.debug( fields, msg, ...) * @@ -545,6 +551,10 @@ Logger.prototype.debug = function () { return (this.level <= DEBUG); } else if (this.level > DEBUG) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.debug(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.debug(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -561,6 +571,7 @@ Logger.prototype.debug = function () { * * Usages: * log.info() -> boolean is-info-enabled + * log.info( err) * log.info( msg, ...) * log.info( fields, msg, ...) * @@ -575,6 +586,10 @@ Logger.prototype.info = function () { return (this.level <= INFO); } else if (this.level > INFO) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.info(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.info(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -591,6 +606,7 @@ Logger.prototype.info = function () { * * Usages: * log.warn() -> boolean is-warn-enabled + * log.warn( err) * log.warn( msg, ...) * log.warn( fields, msg, ...) * @@ -605,6 +621,10 @@ Logger.prototype.warn = function () { return (this.level <= WARN); } else if (this.level > WARN) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.warn(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.warn(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -621,6 +641,7 @@ Logger.prototype.warn = function () { * * Usages: * log.error() -> boolean is-error-enabled + * log.error( err) * log.error( msg, ...) * log.error( fields, msg, ...) * @@ -635,6 +656,10 @@ Logger.prototype.error = function () { return (this.level <= ERROR); } else if (this.level > ERROR) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.error(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.error(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -651,6 +676,7 @@ Logger.prototype.error = function () { * * Usages: * log.fatal() -> boolean is-fatal-enabled + * log.fatal( err) * log.fatal( msg, ...) * log.fatal( fields, msg, ...) * @@ -665,6 +691,10 @@ Logger.prototype.fatal = function () { return (this.level <= FATAL); } else if (this.level > FATAL) { return; + } else if (arguments.length === 1 && arguments[0] instanceof Error) { + // `log.fatal(err)` + fields = {err: errSerializer(arguments[0])}; + msgArgs = [fields.err.message]; } else if (typeof arguments[0] === 'string') { // `log.fatal(msg, ...)` fields = null; msgArgs = Array.prototype.slice.call(arguments); @@ -711,7 +741,7 @@ Logger.stdSerializers.res = function res(res) { // Serialize an Error object // (Core error properties are enumerable in node 0.4, not in 0.6). -Logger.stdSerializers.err = function err(err) { +var errSerializer = Logger.stdSerializers.err = function err(err) { var obj = { message: err.message, name: err.name, diff --git a/package.json b/package.json index f826387..06eaa6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bunyan", - "version": "0.4.1", + "version": "0.5.0", "description": "a JSON Logger library for node.js servers", "main": "./lib/bunyan.js", "bin": {