Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

bunyan

trentm8.4mMIT1.8.15TypeScript support: definitely-typed

a JSON logging library for node.js services

log, logging, log4j, json, bunyan

readme

npm version Build Status

Bunyan is a simple and fast JSON logging library for node.js services:

var bunyan = require('bunyan');
var log = bunyan.createLogger({name: "myapp"});
log.info("hi");

and a bunyan CLI tool for nicely viewing those logs:

bunyan CLI screenshot

Manifesto: Server logs should be structured. JSON's a good format. Let's do that. A log record is one line of JSON.stringify'd output. Let's also specify some common names for the requisite and common fields for a log record (see below).

Table of Contents

Current Status

Solid core functionality is there. Joyent is using this for a number of production services. Bunyan supports node 0.10 and greater. Follow @trentmick for updates to Bunyan.

There is an email discussion list bunyan-logging@googlegroups.com, also as a forum in the browser.

Installation

npm install bunyan

Tip: The bunyan CLI tool is written to be compatible (within reason) with all versions of Bunyan logs. Therefore you might want to npm install -g bunyan to get the bunyan CLI on your PATH, then use local bunyan installs for node.js library usage of bunyan in your apps.

Tip: Installing without optional dependencies can dramatically reduce bunyan's install size. dtrace-provider is used for dtrace features, mv is used for RotatingFileStream, and moment is used for local time. If you don't need these features, consider installing with the --no-optional flag.

Features

Introduction

Like most logging libraries you create a Logger instance and call methods named after the logging levels:

// hi.js
var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});
log.info('hi');
log.warn({lang: 'fr'}, 'au revoir');

All loggers must provide a "name". This is somewhat akin to the log4j logger "name", but Bunyan doesn't do hierarchical logger names.

Bunyan log records are JSON. A few fields are added automatically: "pid", "hostname", "time" and "v".

$ node hi.js
{"name":"myapp","hostname":"banana.local","pid":40161,"level":30,"msg":"hi","time":"2013-01-04T18:46:23.851Z","v":0}
{"name":"myapp","hostname":"banana.local","pid":40161,"level":40,"lang":"fr","msg":"au revoir","time":"2013-01-04T18:46:23.853Z","v":0}

Constructor API

var bunyan = require('bunyan');
var log = bunyan.createLogger({
    name: <string>,                     // Required
    level: <level name or number>,      // Optional, see "Levels" section
    stream: <node.js stream>,           // Optional, see "Streams" section
    streams: [<bunyan streams>, ...],   // Optional, see "Streams" section
    serializers: <serializers mapping>, // Optional, see "Serializers" section
    src: <boolean>,                     // Optional, see "src" section

    // Any other fields are added to all log records as is.
    foo: 'bar',
    ...
});

Log Method API

The example above shows two different ways to call log.info(...). The full API is:

log.info();     // Returns a boolean: is the "info" level enabled?
                // This is equivalent to `log.isInfoEnabled()` or
                // `log.isEnabledFor(INFO)` in log4j.

log.info('hi');                     // Log a simple string message (or number).
log.info('hi %s', bob, anotherVar); // Uses `util.format` for msg formatting.

log.info({foo: 'bar'}, 'hi');
                // The first field can optionally be a "fields" object, which
                // is merged into the log record.

log.info(err);  // Special case to log an `Error` instance to the record.
                // This adds an "err" field with exception details
                // (including the stack) and sets "msg" to the exception
                // message.
log.info(err, 'more on this: %s', more);
                // ... or you can specify the "msg".

log.info({foo: 'bar', err: err}, 'some msg about this error');
                // To pass in an Error *and* other fields, use the `err`
                // field name for the Error instance.

Note that this implies you cannot blindly pass any object as the first argument to log it because that object might include fields that collide with Bunyan's core record fields. In other words, log.info(mywidget) may not yield what you expect. Instead of a string representation of mywidget that other logging libraries may give you, Bunyan will try to JSON-ify your object. It is a Bunyan best practice to always give a field name to included objects, e.g.:

log.info({widget: mywidget}, ...)

This will dove-tail with Bunyan serializer support, discussed later.

The same goes for all of Bunyan's log levels: log.trace, log.debug, log.info, log.warn, log.error, and log.fatal. See the levels section below for details and suggestions.

CLI Usage

Bunyan log output is a stream of JSON objects. This is great for processing, but not for reading directly. A bunyan tool is provided for pretty-printing bunyan logs and for filtering (e.g. | bunyan -c 'this.foo == "bar"'). Using our example above:

$ node hi.js | ./node_modules/.bin/bunyan
[2013-01-04T19:01:18.241Z]  INFO: myapp/40208 on banana.local: hi
[2013-01-04T19:01:18.242Z]  WARN: myapp/40208 on banana.local: au revoir (lang=fr)

See the screenshot above for an example of the default coloring of rendered log output. That example also shows the nice formatting automatically done for some well-known log record fields (e.g. req is formatted like an HTTP request, res like an HTTP response, err like an error stack trace).

One interesting feature is filtering of log content, which can be useful for digging through large log files or for analysis. We can filter only records above a certain level:

$ node hi.js | bunyan -l warn
[2013-01-04T19:08:37.182Z]  WARN: myapp/40353 on banana.local: au revoir (lang=fr)

Or filter on the JSON fields in the records (e.g. only showing the French records in our contrived example):

$ node hi.js | bunyan -c 'this.lang == "fr"'
[2013-01-04T19:08:26.411Z]  WARN: myapp/40342 on banana.local: au revoir (lang=fr)

See bunyan --help for other facilities.

Streams Introduction

By default, log output is to stdout and at the "info" level. Explicitly that looks like:

var log = bunyan.createLogger({
    name: 'myapp',
    stream: process.stdout,
    level: 'info'
});

That is an abbreviated form for a single stream. You can define multiple streams at different levels.

var log = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'info',
      stream: process.stdout            // log INFO and above to stdout
    },
    {
      level: 'error',
      path: '/var/tmp/myapp-error.log'  // log ERROR and above to a file
    }
  ]
});

More on streams in the Streams section below.

log.child

Bunyan has a concept of a child logger to specialize a logger for a sub-component of your application, i.e. to create a new logger with additional bound fields that will be included in its log records. A child logger is created with log.child(...).

In the following example, logging on a "Wuzzle" instance's this.log will be exactly as on the parent logger with the addition of the widget_type field:

var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});

function Wuzzle(options) {
    this.log = options.log.child({widget_type: 'wuzzle'});
    this.log.info('creating a wuzzle')
}
Wuzzle.prototype.woos = function () {
    this.log.warn('This wuzzle is woosey.')
}

log.info('start');
var wuzzle = new Wuzzle({log: log});
wuzzle.woos();
log.info('done');

Running that looks like (raw):

$ node myapp.js
{"name":"myapp","hostname":"myhost","pid":34572,"level":30,"msg":"start","time":"2013-01-04T07:47:25.814Z","v":0}
{"name":"myapp","hostname":"myhost","pid":34572,"widget_type":"wuzzle","level":30,"msg":"creating a wuzzle","time":"2013-01-04T07:47:25.815Z","v":0}
{"name":"myapp","hostname":"myhost","pid":34572,"widget_type":"wuzzle","level":40,"msg":"This wuzzle is woosey.","time":"2013-01-04T07:47:25.815Z","v":0}
{"name":"myapp","hostname":"myhost","pid":34572,"level":30,"msg":"done","time":"2013-01-04T07:47:25.816Z","v":0}

And with the bunyan CLI (using the "short" output mode):

$ node myapp.js  | bunyan -o short
07:46:42.707Z  INFO myapp: start
07:46:42.709Z  INFO myapp: creating a wuzzle (widget_type=wuzzle)
07:46:42.709Z  WARN myapp: This wuzzle is woosey. (widget_type=wuzzle)
07:46:42.709Z  INFO myapp: done

A more practical example is in the node-restify web framework. Restify uses Bunyan for its logging. One feature of its integration, is that if server.use(restify.requestLogger()) is used, each restify request handler includes a req.log logger that is:

log.child({req_id: <unique request id>}, true)

Apps using restify can then use req.log and have all such log records include the unique request id (as "req_id"). Handy.

Serializers

Bunyan has a concept of "serializer" functions to produce a JSON-able object from a JavaScript object, so you can easily do the following:

log.info({req: <request object>}, 'something about handling this request');

and have the req entry in the log record be just a reasonable subset of <request object> fields (or computed data about those fields).

A logger instance can have a serializers mapping of log record field name ("req" in this example) to a serializer function. When creating the log record, Bunyan will call the serializer function for fields of that name. An example:

function reqSerializer(req) {
    return {
        method: req.method,
        url: req.url,
        headers: req.headers
    };
}
var log = bunyan.createLogger({
    name: 'myapp',
    serializers: {
        req: reqSerializer
    }
});

Typically serializers are added to a logger at creation time via bunyan.createLogger({..., serializers: <serializers>}). However, serializers can be added after creation via <logger>.addSerializers(...), e.g.:

var log = bunyan.createLogger({name: 'myapp'});
log.addSerializers({req: reqSerializer});

Requirements for serializers functions

A serializer function is passed unprotected objects that are passed to the log.info, log.debug, etc. call. This means a poorly written serializer function can cause side-effects. Logging shouldn't do that. Here are a few rules and best practices for serializer functions:

  • A serializer function should never throw. The bunyan library does protect somewhat from this: if the serializer throws an error, then bunyan will (a) write an ugly message on stderr (along with the traceback), and (b) the field in the log record will be replaced with a short error message. For example:

      bunyan: ERROR: Exception thrown from the "foo" Bunyan serializer. This should never happen. This is a bug in that serializer function.
      TypeError: Cannot read property 'not' of undefined
          at Object.fooSerializer [as foo] (/Users/trentm/tm/node-bunyan/bar.js:8:26)
          at /Users/trentm/tm/node-bunyan/lib/bunyan.js:873:50
          at Array.forEach (native)
          at Logger._applySerializers (/Users/trentm/tm/node-bunyan/lib/bunyan.js:865:35)
          at mkRecord (/Users/trentm/tm/node-bunyan/lib/bunyan.js:978:17)
          at Logger.info (/Users/trentm/tm/node-bunyan/lib/bunyan.js:1044:19)
          at Object.<anonymous> (/Users/trentm/tm/node-bunyan/bar.js:13:5)
          at Module._compile (module.js:409:26)
          at Object.Module._extensions..js (module.js:416:10)
          at Module.load (module.js:343:32)
      {"name":"bar","hostname":"danger0.local","pid":47411,"level":30,"foo":"(Error in Bunyan log \"foo\" serializer broke field. See stderr for details.)","msg":"one","time":"2017-03-08T02:53:51.173Z","v":0}
  • A serializer function should never mutate the given object. Doing so will change the object in your application.

  • A serializer function should be defensive. In my experience, it is common to set a serializer in an app, say for field name "foo", and then accidentally have a log line that passes a "foo" that is undefined, or null, or of some unexpected type. A good start at defensiveness is to start with this:

      function fooSerializer(foo) {
          // Guard against foo be null/undefined. Check that expected fields
          // are defined.
          if (!foo || !foo.bar)
              return foo;
          var obj = {
              // Create the object to be logged.
              bar: foo.bar
          }
          return obj;
      };

Standard Serializers

Bunyan includes a small set of "standard serializers", exported as bunyan.stdSerializers. Their use is completely optional. An example using all of them:

var log = bunyan.createLogger({
    name: 'myapp',
    serializers: bunyan.stdSerializers
});

or particular ones:

var log = bunyan.createLogger({
    name: 'myapp',
    serializers: {err: bunyan.stdSerializers.err}
});

Standard serializers are:

Field Description
err Used for serializing JavaScript error objects, including traversing an error's cause chain for error objects with a .cause() -- e.g. as from verror.
req Common fields from a node.js HTTP request object.
res Common fields from a node.js HTTP response object.

Note that the req and res serializers intentionally do not include the request/response body, as that can be prohibitively large. If helpful, the restify framework's audit logger plugin has its own req/res serializers that include more information (optionally including the body).

src

The source file, line and function of the log call site can be added to log records by using the src: true config option:

var log = bunyan.createLogger({src: true, ...});

This adds the call source info with the 'src' field, like this:

{
  "name": "src-example",
  "hostname": "banana.local",
  "pid": 123,
  "component": "wuzzle",
  "level": 4,
  "msg": "This wuzzle is woosey.",
  "time": "2012-02-06T04:19:35.605Z",
  "src": {
    "file": "/Users/trentm/tm/node-bunyan/examples/src.js",
    "line": 20,
    "func": "Wuzzle.woos"
  },
  "v": 0
}

WARNING: Determining the call source info is slow. Never use this option in production.

Levels

The log levels in bunyan are as follows. The level descriptions are best practice opinions of the author.

  • "fatal" (60): The service/app is going to stop or become unusable now. An operator should definitely look into this soon.
  • "error" (50): Fatal for a particular request, but the service/app continues servicing other requests. An operator should look at this soon(ish).
  • "warn" (40): A note on something that should probably be looked at by an operator eventually.
  • "info" (30): Detail on regular operation.
  • "debug" (20): Anything else, i.e. too verbose to be included in "info" level.
  • "trace" (10): Logging from external libraries used by your app or very detailed application logging.

Setting a logger instance (or one of its streams) to a particular level implies that all log records at that level and above are logged. E.g. a logger set to level "info" will log records at level info and above (warn, error, fatal).

While using log level names is preferred, the actual level values are integers internally (10 for "trace", ..., 60 for "fatal"). Constants are defined for the levels: bunyan.TRACE ... bunyan.FATAL. The lowercase level names are aliases supported in the API, e.g. log.level("info"). There is one exception: DTrace integration uses the level names. The fired DTrace probes are named 'bunyan-$levelName'.

Here is the API for querying and changing levels on an existing logger. Recall that a logger instance has an array of output "streams":

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

Level suggestions

Trent's biased suggestions for server apps: Use "debug" sparingly. Information that will be useful to debug errors post mortem should usually be included in "info" messages if it's generally relevant or else with the corresponding "error" event. Don't rely on spewing mostly irrelevant debug messages all the time and sifting through them when an error occurs.

Trent's biased suggestions for node.js libraries: IMHO, libraries should only ever log at trace-level. Fine control over log output should be up to the app using a library. Having a library that spews log output at higher levels gets in the way of a clear story in the app logs.

Log Record Fields

This section will describe rules for the Bunyan log format: field names, field meanings, required fields, etc. However, a Bunyan library doesn't strictly enforce all these rules while records are being emitted. For example, Bunyan will add a time field with the correct format to your log records, but you can specify your own. It is the caller's responsibility to specify the appropriate format.

The reason for the above leniency is because IMO logging a message should never break your app. This leads to this rule of logging: a thrown exception from log.info(...) or equivalent (other than for calling with the incorrect signature) is always a bug in Bunyan.

A typical Bunyan log record looks like this:

{"name":"myserver","hostname":"banana.local","pid":123,"req":{"method":"GET","url":"/path?q=1#anchor","headers":{"x-hi":"Mom","connection":"close"}},"level":3,"msg":"start request","time":"2012-02-03T19:02:46.178Z","v":0}

Pretty-printed:

{
  "name": "myserver",
  "hostname": "banana.local",
  "pid": 123,
  "req": {
    "method": "GET",
    "url": "/path?q=1#anchor",
    "headers": {
      "x-hi": "Mom",
      "connection": "close"
    },
    "remoteAddress": "120.0.0.1",
    "remotePort": 51244
  },
  "level": 3,
  "msg": "start request",
  "time": "2012-02-03T19:02:57.534Z",
  "v": 0
}

Core fields

  • v: Required. Integer. Added by Bunyan. Cannot be overridden. This is the Bunyan log format version (require('bunyan').LOG_VERSION). The log version is a single integer. 0 is until I release a version "1.0.0" of node-bunyan. Thereafter, starting with 1, this will be incremented if there is any backward incompatible change to the log record format. Details will be in "CHANGES.md" (the change log).
  • level: Required. Integer. Added by Bunyan. Cannot be overridden. See the "Levels" section.
  • name: Required. String. Provided at Logger creation. You must specify a name for your logger when creating it. Typically this is the name of the service/app using Bunyan for logging.
  • hostname: Required. String. Provided or determined at Logger creation. You can specify your hostname at Logger creation or it will be retrieved via os.hostname().
  • pid: Required. Integer. Filled in automatically at Logger creation.
  • time: Required. String. Added by Bunyan. Can be overridden. The date and time of the event in ISO 8601 Extended Format format and in UTC, as from Date.toISOString().
  • msg: Required. String. Every log.debug(...) et al call must provide a log message.
  • src: Optional. Object giving log call source info. This is added automatically by Bunyan if the "src: true" config option is given to the Logger. Never use in production as this is really slow.

Go ahead and add more fields, and nested ones are fine (and recommended) as well. This is why we're using JSON. Some suggestions and best practices follow (feedback from actual users welcome).

  • 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.<anonymous> ..."
      },
      "msg": "boom",
      ...

    Or use the bunyan.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 for a request. This really shines when you have a SOA with multiple services and you carry a single request ID from the top API down through all APIs (as node-restify facilitates with its 'Request-Id' header).

  • req: An HTTP server request. Bunyan provides bunyan.stdSerializers.req to serialize a request with a suggested set of keys. Example:

      {
        "method": "GET",
        "url": "/path?q=1#anchor",
        "headers": {
          "x-hi": "Mom",
          "connection": "close"
        },
        "remoteAddress": "120.0.0.1",
        "remotePort": 51244
      }
  • res: An HTTP server response. Bunyan provides bunyan.stdSerializers.res to serialize a response with a suggested set of keys. Example:

      {
        "statusCode": 200,
        "header": "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n"
      }

Other fields to consider

  • req.username: Authenticated user (or for a 401, the user attempting to auth).
  • Some mechanism to calculate response latency. "restify" users will have an "X-Response-Time" header. A latency custom field would be fine.
  • req.body: If you know that request bodies are small (common in APIs, for example), then logging the request body is good.

Streams

A "stream" is Bunyan's name for where it outputs log messages (the equivalent to a log4j Appender). Ultimately Bunyan uses a Writable Stream interface, but there are some additional attributes used to create and manage the stream. A Bunyan Logger instance has one or more streams. In general streams are specified with the "streams" option:

var bunyan = require('bunyan');
var log = bunyan.createLogger({
    name: "foo",
    streams: [
        {
            stream: process.stderr,
            level: "debug"
        },
        ...
    ]
});

For convenience, if there is only one stream, it can be specified with the "stream" and "level" options (internally converted to a Logger.streams).

var log = bunyan.createLogger({
    name: "foo",
    stream: process.stderr,
    level: "debug"
});

Note that "file" streams do not support this shortcut (partly for historical reasons and partly to not make it difficult to add a literal "path" field on log records).

If neither "streams" nor "stream" are specified, the default is a stream of type "stream" emitting to process.stdout at the "info" level.

Adding a Stream

After a bunyan instance has been initialized, you may add additional streams by calling the addStream function.

var bunyan = require('bunyan');
var log = bunyan.createLogger('myLogger');
log.addStream({
  name: "myNewStream",
  stream: process.stderr,
  level: "debug"
});

stream errors

A Bunyan logger instance can be made to re-emit "error" events from its streams. Bunyan does so by default for type === "file" streams, so you can do this:

var log = bunyan.createLogger({name: 'mylog', streams: [{path: LOG_PATH}]});
log.on('error', function (err, stream) {
    // Handle stream write or create error here.
});

As of bunyan@1.7.0, the reemitErrorEvents field can be used when adding a stream to control whether "error" events are re-emitted on the Logger. For example:

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function MyFlakyStream() {}
util.inherits(MyFlakyStream, EventEmitter);

MyFlakyStream.prototype.write = function (rec) {
    this.emit('error', new Error('boom'));
}

var log = bunyan.createLogger({
    name: 'this-is-flaky',
    streams: [
        {
            type: 'raw',
            stream: new MyFlakyStream(),
            reemitErrorEvents: true
        }
    ]
});
log.info('hi there');

The behaviour is as follows:

  • reemitErrorEvents not specified: file streams will re-emit error events on the Logger instance.
  • reemitErrorEvents: true: error events will be re-emitted on the Logger for any stream with a .on() function -- which includes file streams, process.stdout/stderr, and any object that inherits from EventEmitter.
  • reemitErrorEvents: false: error events will not be re-emitted for any streams.

Note: "error" events are not related to log records at the "error" level as produced by log.error(...). See the node.js docs on error events for details.

stream type: stream

A type === 'stream' is a plain ol' node.js Writable Stream. A "stream" (the writable stream) field is required. E.g.: process.stdout, process.stderr.

var log = bunyan.createLogger({
    name: 'foo',
    streams: [{
        stream: process.stderr
        // `type: 'stream'` is implied
    }]
});
Field Required? Default Description
stream Yes - A "Writable Stream", e.g. a std handle or an open file write stream.
type No n/a `type == 'stream'` is implied if the `stream` field is given.
level No info The level to which logging to this stream is enabled. If not specified it defaults to "info". If specified this can be one of the level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`, `bunyan.DEBUG`, ...). This serves as a severity threshold for that stream so logs of greater severity will also pass through (i.e. If level="warn", error and fatal will also pass through this stream).
name No - A name for this stream. This may be useful for usage of `log.level(NAME, LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't used for anything else.

stream type: file

A type === 'file' stream requires a "path" field. Bunyan will open this file for appending. E.g.:

var log = bunyan.createLogger({
    name: 'foo',
    streams: [{
        path: '/var/log/foo.log',
        // `type: 'file'` is implied
    }]
});
Field Required? Default Description
path Yes - A file path to which to log.
type No n/a `type == 'file'` is implied if the `path` field is given.
level No info The level to which logging to this stream is enabled. If not specified it defaults to "info". If specified this can be one of the level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`, `bunyan.DEBUG`, ...). This serves as a severity threshold for that stream so logs of greater severity will also pass through (i.e. If level="warn", error and fatal will also pass through this stream).
name No - A name for this stream. This may be useful for usage of `log.level(NAME, LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't used for anything else.

stream type: rotating-file

WARNING on node 0.8 usage: Users of Bunyan's rotating-file should (a) be using at least bunyan 0.23.1 (with the fix for this issue), and (b) should use at least node 0.10 (node 0.8 does not support the unref() method on setTimeout(...) needed for the mentioned fix). The symptom is that process termination will hang for up to a full rotation period.

WARNING on cluster usage: Using Bunyan's rotating-file stream with node.js's "cluster" module can result in unexpected file rotation. You must not have multiple processes in the cluster logging to the same file path. In other words, you must have a separate log file path for the master and each worker in the cluster. Alternatively, consider using a system file rotation facility such as logrotate on Linux or logadm on SmartOS/Illumos. See this comment on issue #117 for details.

A type === 'rotating-file' is a file stream that handles file automatic rotation.

var log = bunyan.createLogger({
    name: 'foo',
    streams: [{
        type: 'rotating-file',
        path: '/var/log/foo.log',
        period: '1d',   // daily rotation
        count: 3        // keep 3 back copies
    }]
});

This will rotate '/var/log/foo.log' every day (at midnight) to:

/var/log/foo.log.0     # yesterday
/var/log/foo.log.1     # 1 day ago
/var/log/foo.log.2     # 2 days ago

Currently, there is no support for providing a template for the rotated files, or for rotating when the log reaches a threshold size.

Field Required? Default Description
type Yes - "rotating-file"
path Yes - A file path to which to log. Rotated files will be "$path.0", "$path.1", ...
period No 1d The period at which to rotate. This is a string of the format "$number$scope" where "$scope" is one of "ms" (milliseconds -- only useful for testing), "h" (hours), "d" (days), "w" (weeks), "m" (months), "y" (years). Or one of the following names can be used "hourly" (means 1h), "daily" (1d), "weekly" (1w), "monthly" (1m), "yearly" (1y). Rotation is done at the start of the scope: top of the hour (h), midnight (d), start of Sunday (w), start of the 1st of the month (m), start of Jan 1st (y).
count No 10 The number of rotated files to keep.
level No info The level at which logging to this stream is enabled. If not specified it defaults to "info". If specified this can be one of the level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`, `bunyan.DEBUG`, ...).
name No - A name for this stream. This may be useful for usage of `log.level(NAME, LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't used for anything else.

Note on log rotation: Often you may be using external log rotation utilities like logrotate on Linux or logadm on SmartOS/Illumos. In those cases, unless you are ensuring "copy and truncate" semantics (via copytruncate with logrotate or -c with logadm) then the fd for your 'file' stream will change. You can tell bunyan to reopen the file stream with code like this in your app:

var log = bunyan.createLogger(...);
...
process.on('SIGUSR2', function () {
    log.reopenFileStreams();
});

where you'd configure your log rotation to send SIGUSR2 (or some other signal) to your process. Any other mechanism to signal your app to run log.reopenFileStreams() would work as well.

stream type: raw

  • raw: Similar to a "stream" writable stream, except that the write method is given raw log record Objects instead of a JSON-stringified string. This can be useful for hooking on further processing to all Bunyan logging: pushing to an external service, a RingBuffer (see below), etc.

raw + RingBuffer Stream

Bunyan comes with a special stream called a RingBuffer which keeps the last N records in memory and does not write the data anywhere else. One common strategy is to log 'info' and higher to a normal log file but log all records (including 'trace') to a ringbuffer that you can access via a debugger, or your own HTTP interface, or a post-mortem facility like MDB or node-panic.

To use a RingBuffer:

/* Create a ring buffer that stores the last 100 records. */
var bunyan = require('bunyan');
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
var log = bunyan.createLogger({
    name: 'foo',
    streams: [
        {
            level: 'info',
            stream: process.stdout
        },
        {
            level: 'trace',
            type: 'raw',    // use 'raw' to get raw log record objects
            stream: ringbuffer
        }
    ]
});

log.info('hello world');
console.log(ringbuffer.records);

This example emits:

[ { name: 'foo',
    hostname: '912d2b29',
    pid: 50346,
    level: 30,
    msg: 'hello world',
    time: '2012-06-19T21:34:19.906Z',
    v: 0 } ]

third-party streams

See the user-maintained list in the Bunyan wiki.

Runtime log snooping via DTrace

On systems that support DTrace (e.g., illumos derivatives like SmartOS and OmniOS, FreeBSD, Mac), Bunyan will create a DTrace provider (bunyan) that makes available the following probes:

log-trace
log-debug
log-info
log-warn
log-error
log-fatal

Each of these probes has a single argument: the string that would be written to the log. Note that when a probe is enabled, it will fire whenever the corresponding function is called, even if the level of the log message is less than that of any stream.

DTrace examples

Trace all log messages coming from any Bunyan module on the system. (The -x strsize=4k is to raise dtrace's default 256 byte buffer size because log messages are longer than typical dtrace probes.)

dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%d: %s: %s", pid, probefunc, copyinstr(arg0))}'

Trace all log messages coming from the "wuzzle" component:

dtrace -x strsize=4k -qn 'bunyan*:::log-*/strstr(this->str = copyinstr(arg0), "\"component\":\"wuzzle\"") != NULL/{printf("%s", this->str)}'

Aggregate debug messages from process 1234, by message:

dtrace -x strsize=4k -n 'bunyan1234:::log-debug{@[copyinstr(arg0)] = count()}'

Have the bunyan CLI pretty-print the traced logs:

dtrace -x strsize=4k -qn 'bunyan1234:::log-*{printf("%s", copyinstr(arg0))}' | bunyan

A convenience handle has been made for this:

bunyan -p 1234

On systems that support the jstack action via a node.js helper, get a stack backtrace for any debug message that includes the string "danger!":

dtrace -x strsize=4k -qn 'log-debug/strstr(copyinstr(arg0), "danger!") != NULL/{printf("\n%s", copyinstr(arg0)); jstack()}'

Output of the above might be:

{"name":"foo","hostname":"763bf293-d65c-42d5-872b-4abe25d5c4c7.local","pid":12747,"level":20,"msg":"danger!","time":"2012-10-30T18:28:57.115Z","v":0}

          node`0x87e2010
          DTraceProviderBindings.node`usdt_fire_probe+0x32
          DTraceProviderBindings.node`_ZN4node11DTraceProbe5_fireEN2v85LocalINS1_5ValueEEE+0x32d
          DTraceProviderBindings.node`_ZN4node11DTraceProbe4FireERKN2v89ArgumentsE+0x77
          << internal code >>
          (anon) as (anon) at /root/node-bunyan/lib/bunyan.js position 40484
          << adaptor >>
          (anon) as doit at /root/my-prog.js position 360
          (anon) as list.ontimeout at timers.js position 4960
          << adaptor >>
          << internal >>
          << entry >>
          node`_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb+0x101
          node`_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb+0xcb
          node`_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE+0xf0
          node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_8FunctionEEEiPNS1_INS0_5ValueEEE+0x11f
          node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_6StringEEEiPNS1_INS0_5ValueEEE+0x66
          node`_ZN4node9TimerWrap9OnTimeoutEP10uv_timer_si+0x63
          node`uv__run_timers+0x66
          node`uv__run+0x1b
          node`uv_run+0x17
          node`_ZN4node5StartEiPPc+0x1d0
          node`main+0x1b
          node`_start+0x83

          node`0x87e2010
          DTraceProviderBindings.node`usdt_fire_probe+0x32
          DTraceProviderBindings.node`_ZN4node11DTraceProbe5_fireEN2v85LocalINS1_5ValueEEE+0x32d
          DTraceProviderBindings.node`_ZN4node11DTraceProbe4FireERKN2v89ArgumentsE+0x77
          << internal code >>
          (anon) as (anon) at /root/node-bunyan/lib/bunyan.js position 40484
          << adaptor >>
          (anon) as doit at /root/my-prog.js position 360
          (anon) as list.ontimeout at timers.js position 4960
          << adaptor >>
          << internal >>
          << entry >>
          node`_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb+0x101
          node`_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb+0xcb
          node`_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE+0xf0
          node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_8FunctionEEEiPNS1_INS0_5ValueEEE+0x11f
          node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_6StringEEEiPNS1_INS0_5ValueEEE+0x66
          node`_ZN4node9TimerWrap9OnTimeoutEP10uv_timer_si+0x63
          node`uv__run_timers+0x66
          node`uv__run+0x1b
          node`uv_run+0x17
          node`_ZN4node5StartEiPPc+0x1d0
          node`main+0x1b
          node`_start+0x83

Runtime environments

Node-bunyan supports running in a few runtime environments:

Support for other runtime environments is welcome. If you have suggestions, fixes, or mentions that node-bunyan already works in some other JavaScript runtime, please open an issue or a pull request.

The primary target is Node.js. It is the only environment in which I regularly test. If you have suggestions for how to automate testing for other environments, I'd appreciate feedback on this automated testing issue.

Browserify

As the Browserify site says it "lets you require('modules') in the browser by bundling up all of your dependencies." It is a build tool to run on your node.js script to bundle up your script and all its node.js dependencies into a single file that is runnable in the browser via:

<script src="play.browser.js"></script>

As of version 1.1.0, node-bunyan supports being run via Browserify. The default stream when running in the browser is one that emits raw log records to console.log/info/warn/error.

Here is a quick example showing you how you can get this working for your script.

  1. Get browserify and bunyan installed in your module:

     $ npm install browserify bunyan
  2. An example script using Bunyan, "play.js":

     var bunyan = require('bunyan');
     var log = bunyan.createLogger({name: 'play', level: 'debug'});
     log.trace('this one does not emit');
     log.debug('hi on debug');   // console.log
     log.info('hi on info');     // console.info
     log.warn('hi on warn');     // console.warn
     log.error('hi on error');   // console.error
  3. Build this into a bundle to run in the browser, "play.browser.js":

     $ ./node_modules/.bin/browserify play.js -o play.browser.js
  4. Put that into an HTML file, "play.html":

     <!DOCTYPE html>
     <html>
     <head>
       <meta charset="utf-8">
       <script src="play.browser.js"></script>
     </head>
     <body>
       <div>hi</div>
     </body>
     </html>
  5. Open that in your browser and open your browser console:

     $ open play.html

Here is what it looks like in Firefox's console: Bunyan + Browserify in the Firefox console

For some, the raw log records might not be desired. To have a rendered log line you'll want to add your own stream, starting with something like this:

var bunyan = require('./lib/bunyan');

function MyRawStream() {}
MyRawStream.prototype.write = function (rec) {
    console.log('[%s] %s: %s',
        rec.time.toISOString(),
        bunyan.nameFromLevel[rec.level],
        rec.msg);
}

var log = bunyan.createLogger({
    name: 'play',
    streams: [
        {
            level: 'info',
            stream: new MyRawStream(),
            type: 'raw'
        }
    ]
});

log.info('hi on info');

webpack

To include bunyan in your webpack bundle you need to tell webpack to ignore the optional dependencies that are unavailable in browser environments.

Mark the following dependencies as externals in your webpack configuration file to exclude them from the bundle:

module: {
    externals: ['dtrace-provider', 'fs', 'mv', 'os', 'source-map-support']
}

Versioning

All versions are <major>.<minor>.<patch> which will be incremented for breaking backward compat and major reworks, new features without breaking change, and bug fixes, respectively. tl;dr: Semantic versioning.

License

MIT.

See Also

See the user-maintained list of Bunyan-related software in the Bunyan wiki.

changelog

bunyan Changelog

See the bunyan@2.x changelog for details on recent 2.x releases.

Known issues:

not yet released

(nothing yet)

1.8.15

  • [pull #575, #278] Change the default "req" serializer to accept expressjs's req.originalUrl for the "url" field per https://expressjs.com/en/api.html#req.originalUrl. (By @twelve17 and @kingcody.)
  • Development change: Switch to node-tap for testing (from nodeunit, which is now obsolete). Currently just tap v9 because that is the last major version of node-tap that supports back to node v0.10.

1.8.14

  • [pull #558] Update minimum "moment" version to 2.19.3 for CVE-2017-18214.
  • [issue #589] Use os.EOL for newlines in bunyan output, which helps with some Unix-EOL-naive apps like notepad. (By @bwknight877.)
  • Development change: Switched to GitHub Actions for CI.

1.8.13

  • Fix a vulnerability from a crafted argument to 'bunyan -p ARG'

    This was reported privately as:

    https://hackerone.com/reports/902739
    bunyan - RCE via insecure command formatting

    Previous to this version the 'bunyan' CLI was not escaping a given argument to the '-p' option before executing ps -A -o pid,command | grep '$ARG' which could lead to unintended execution.

1.8.12

  • [issue #444] Fix the bunyan CLI to not duplicate the "HTTP/1.1 ..." status line when serializing a "res" field.

1.8.11

  • [issue #504] The bunyan 1.x CLI adds a Host: $client_req.address[:$client_req.port] header when rendering a client_req field in a log record. Fix that here to: (a) not add it if client_req.headers already includes a host header; and (b) not include the given port if it is 80 or 443 (assuming that is the default port. Note: bunyan 2.x CLI will stop adding this Host header because it is a guess that can be wrong and misleading.

1.8.10

  • Ensure that bunyan errors out if attempting to use -p PID and file args at the same time.

1.8.9

  • [pull #409, issue #246] Revert a change added to the bunyan CLI version 1.0.1 where SIGINT was ignored, such that Ctrl+C could not be used to terminate bunyan. (By @zbjornson and @davepacheco.)
  • [pull #469] Fix a strict mode ("use strict;") error in some versions of Safari.

1.8.8

  • Fix breakage due to a silly last minute "fix 'make check'".

1.8.7

Note: Bad release. Use 1.8.8 or later.

  • [issue #484] Fix breakage due to #474 in previous release.

1.8.6

Note: Bad release. Use 1.8.7 or later.

  • [issue #474] Bunyan's safeCycles is too slow when logging large objects.

1.8.5

  • [issue #401] Improved performance when using disabled log levels.

1.8.4

  • [issue #454] Fix src usage with node v7.

1.8.3

  • [issue #450] Fix log.info(null) crash that resulted from #426 in v1.8.2.

1.8.2

  • [issue #449] Bump dtrace-provider dep to 0.7.0 to help avoid deprecation warnings with node v6 in some cases.
  • [issue #426] Ensure log.info({err: err}) results in a "msg" value, just like log.info(err).

1.8.1

  • [pull #386] Fix bad bug in rotation that could cause a crash with error message "cannot start a rotation when already rotating" (by Frankie O'Rourke). The bug was introduced in 1.8.0.

1.8.0

Note: Bad release. An addition in this release broke 'rotating-file' usage. Use 1.8.1 or later.

  • [issue #370] Fix bunyan -p ... (i.e. DTrace integration) on node 4.x and 5.x.
  • [issue #329, pull #330] Update the 'rotating-file' stream to do a file rotation on initialization if the mtime on the file path indicates the last rotation time was missed -- i.e. if the app wasn't running at the time. (by Paul Milham.)

1.7.1

  • [issue #332, pull #355] Ensure stream for type='stream' stream is a writable stream. (By Michael Nisi.)

  • [issue #344] Fix "rotating-file" Bunyan streams to not miss rotations when configured for a period greater than approximately 25 days. Before this there was an issue where periods greater than node.js's maximum setTimeout length would fail to rotate. (By Martijn Schrage.)

  • [issue #234, pull #345] Improve bunyan CLI rendering of "res" field HTTP responses to not show two blank lines for an empty body. (By Michael Nisi.)

1.7.0

  • [pull #311, #302, #310] Improve the runtime environment detection to fix running under NW.js. Contributions by Adam Lynch, Jeremy Ruppel, and Aleksey Timchenko.

  • [pull #318] Add reemitErrorEvents optional boolean for streams added to a Bunyan logger to control whether an "error" event on the stream will be re-emitted on the Logger instance.

      var log = bunyan.createLogger({
          name: 'foo',
          streams: [
              {
                  type: 'raw',
                  stream: new MyCustomStream(),
                  reemitErrorEvents: true
              }
          ]
      });

    Before this change, "error" events were re-emitted on file streams only. The new behaviour is as follows:

    • reemitErrorEvents not specified: file streams will re-emit error events on the Logger instance.
    • reemitErrorEvents: true: error events will be re-emitted on the Logger for any stream with a .on() function -- which includes file streams, process.stdout/stderr, and any object that inherits from EventEmitter.
    • reemitErrorEvents: false: error events will not be re-emitted for any streams.

    Dev Note: Bunyan Logger objects don't currently have a .close() method in which registered error event handlers can be unregistered. That means that a (presumably rare) situation where code adds dozens of Bunyan Logger streams to, e.g. process.stdout, and with reemitErrorEvents: true, could result in leaking Logger objects.

    Original work for allowing "error" re-emitting on non-file streams is by Marc Udoff in pull #318.

1.6.0

  • [pull #304, issue #245] Use [Moment.js][momentjs.com] library to handle bunyan CLI time formatting in some cases, especially to fix display of local time. It is now required for local time formatting (i.e. bunyan -L or bunyan --time local). (By David M. Lee.)

  • [pull #252] Fix errant client_res={} in bunyan CLI rendering, and avoid extra newlines in client_req rendering in some cases. (By Thomas Heymann.)

  • [pull #291, issue #303] Fix LOG.child(...) to not override the "hostname" field of the parent. A use case is when one manually sets "hostname" to something other than os.hostname(). (By github.com/Cactusbone.)

  • [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.

  • Doc updates for #340 and #305.

  • Update make test to test against node 5, 4, 0.12 and 0.10.

1.5.1

  • [issue #296] Fix src: true, which was broken in v1.5.0.

1.5.0

Note: Bad release. The addition of 'use strict'; broke Bunyan's src: true feature. Use 1.5.1 instead.

  • [pull #236, issue #231, issue #223] Fix strict mode in the browser.
  • [pull #282, issue #213] Fixes bunyan to work with webpack. By Denis Izmaylov.
  • [pull #294] Update to dtrace-provider 0.6 to fix with node 4.0 and io.js 3.0.
  • Dropped support for 0.8 (can't install deps easily anymore for running test suite). Bump to a recent iojs version for testing.

1.4.0

(Bumping minor ver b/c I'm wary of dtrace-provider changes. :)

  • [issue #258, pull #259] Update to dtrace-provider 0.5 to fix install and tests on recent io.js versions.
  • safe-json-stringify@1.0.3 changed output, breaking some tests. Fix those.

1.3.6

  • [issue #244] Make bunyan defensive on res.header=null.

1.3.5

  • [issue #233] Make bunyan defensive on res.header as a boolean.
  • [issue #242] Make bunyan defensive on err.stack not being a string.

1.3.4

  • Allow log.child(...) to work even if the logger is a sub-class of Bunyan's Logger class.
  • [issue #219] Hide 'source-map-support' require from browserify.
  • [issue #218] Reset haveNonRawStreams on <logger>.addStream.

1.3.3

  • [pull #127] Update to dtrace-provider 0.4.0, which gives io.js 1.x support for dtrace-y parts of Bunyan.

1.3.2

  • [pull #182] Fallback to using the optional 'safe-json-stringify' module if JSON.stringify throws -- possibly with an enumerable property getter than throws. By Martin Gausby.

1.3.1

  • Export bunyan.RotatingFileStream which is needed if one wants to customize it. E.g. see issue #194.

  • [pull #122] Source Map support for caller line position for the "src" field. This could be interesting for CoffeeScript users of Bunyan. By Manuel Schneider.

  • [issue #164] Ensure a top-level level given in bunyan.createLogger is used for given streams. For example, ensure that the following results in the stream having a DEBUG level:

      var log = bunyan.createLogger({
          name: 'foo',
          level: 'debug',
          streams: [
              {
                  path: '/var/tmp/foo.log'
              }
          ]
      });

    This was broken in the 1.0.1 release. Between that release and 1.3.0 the "/var/tmp/foo.log" stream would be at the INFO level (Bunyan's default level).

1.3.0

  • [issue #103] bunyan -L (or bunyan --time local) to show local time. Bunyan log records store time in UTC time. Sometimes it is convenient to display in local time.

  • [issue #205] Fix the "The Bunyan CLI crashed!" checking to properly warn of the common failure case when -c CONDITION is being used.

1.2.4

  • [issue #210] Export bunyan.nameFromLevel and bunyan.levelFromName. It can be a pain for custom streams to have to reproduce that.

  • [issue #100] Gracefully handle the case of an unbound Logger.{info,debug,...} being used for logging, e.g.:

      myEmittingThing.on('data', log.info)

    Before this change, bunyan would throw. Now it emits a warning to stderr once, and then silently ignores those log attempts, e.g.:

      bunyan usage error: /Users/trentm/tm/node-bunyan/foo.js:12: attempt to log with an unbound log method: `this` is: { _events: { data: [Function] } }

1.2.3

1.2.2

  • Drop the guard that a bunyan Logger level must be between TRACE (10) and FATAL (60), inclusive. This allows a trick of setting the level to FATAL + 1 to turn logging off. While the standard named log levels are the golden path, then intention was not to get in the way of using other level numbers.

1.2.1

  • [issue #178, #181] Get at least dtrace-provider 0.3.1 for optionalDependencies to get a fix for install with decoupled npm (e.g. with homebrew's node and npm).

1.2.0

  • [issue #157] Restore dtrace-provider as a dependency (in "optionalDependencies").

    Dtrace-provider version 0.3.0 add build sugar that should eliminate the problems from older versions: The build is not attempted on Linux and Windows. The build spew is not emitted by default (use V=1 npm install to see it); instead a short warning is emitted if the build fails.

    Also, importantly, the new dtrace-provider fixes working with node v0.11/0.12.

1.1.3

  • [issue #165] Include extra err fields in bunyan CLI output. Before this change only the fields part of the typical node.js error stack (err.stack, err.message, err.name) would be emitted, even though the Bunyan library would typically include err.code and err.signal in the raw JSON log record.

1.1.2

  • Fix a breakage in log.info(err) on a logger with no serializers.

1.1.1

Note: Bad release. It breaks log.info(err) on a logger with no serializers. Use version 1.1.2.

  • [pull #168] Fix handling of log.info(err) to use the log Logger's err serializer if it has one, instead of always using the core Bunyan err serializer. (By Mihai Tomescu.)

1.1.0

1.0.1

  • [issues #105, #138, #151] Export <Logger>.addStream(...) and <Logger>.addSerializers(...) to be able to add them after Logger creation. Thanks @andreineculau!

  • [issue #159] Fix bad handling in construtor guard intending to allow creation without "new": var log = Logger(...). Thanks @rmg!

  • [issue #156] Smaller install size via .npmignore file.

  • [issue #126, #161] Ignore SIGINT (Ctrl+C) when processing stdin. ...| bunyan should expect the preceding process in the pipeline to handle SIGINT. While it is doing so, bunyan should continue to process any remaining output. Thanks @timborodin and @jnordberg!

  • [issue #160] Stop using ANSI 'grey' in bunyan CLI output, because of the problems that causes with Solarized Dark themes (see https://github.com/altercation/solarized/issues/220).

1.0.0

  • [issue #87] Backward incompatible change to -c CODE improving performance by over 10x (good!), with a backward incompatible change to semantics (unfortunate), and adding some sugar (good!).

    The -c CODE implementation was changed to use a JS function for processing rather than vm.runInNewContext. The latter was specatularly slow, so won't be missed. Unfortunately this does mean a few semantic differences in the CODE, the most noticeable of which is that this is required to access the object fields:

      # Bad. Works with bunyan 0.x but not 1.x.
      $ bunyan -c 'pid === 123' foo.log
      ...
    
      # Good. Works with all versions of bunyan
      $ bunyan -c 'this.pid === 123' foo.log
      ...

    The old behaviour of -c can be restored with the BUNYAN_EXEC=vm environment variable:

      $ BUNYAN_EXEC=vm bunyan -c 'pid === 123' foo.log
      ...

    Some sugar was also added: the TRACE, DEBUG, ... constants are defined, so one can:

      $ bunyan -c 'this.level >= ERROR && this.component === "http"' foo.log
      ...

    And example of the speed improvement on a 10 MiB log example:

      $ time BUNYAN_EXEC=vm bunyan -c 'this.level === ERROR' big.log | cat >slow
    
      real    0m6.349s
      user    0m6.292s
      sys    0m0.110s
    
      $ time bunyan -c 'this.level === ERROR' big.log | cat >fast
    
      real    0m0.333s
      user    0m0.303s
      sys    0m0.028s

    The change was courtesy Patrick Mooney (https://github.com/pfmooney). Thanks!

  • Add bunyan -0 ... shortcut for bunyan -o bunyan ....

  • [issue #135] Backward incompatible. Drop dtrace-provider even from optionalDependencies. Dtrace-provider has proven a consistent barrier to installing bunyan, because it is a binary dep. Even as an optional dep it still caused confusion and install noise.

    Users of Bunyan on dtrace-y platforms (SmartOS, Mac, Illumos, Solaris) will need to manually npm install dtrace-provider themselves to get Bunyan's dtrace support to work. If not installed, bunyan should stub it out properly.

0.23.1

0.23.0

  • [issue #139] Fix bunyan crash on a log record with res.header that is an object. A side effect of this improvement is that a record with res.statusCode but no header info will render a response block, for example:

      [2012-08-08T10:25:47.637Z]  INFO: my-service/12859 on my-host: some message (...)
          ...
          --
          HTTP/1.1 200 OK
          --
          ...
  • [pull #42] Fix bunyan crash on a log record with req.headers that is a string (by https://github.com/aexmachina).

  • 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>))

0.22.3

  • Republish the same code to npm.

0.22.2

Note: Bad release. The published package in the npm registry got corrupted. Use 0.22.3 or later.

  • [issue #131] Allow log.info(<number>) and, most importantly, don't crash on that.

  • Update 'mv' optional dep to latest.

0.22.1

  • [issue #111] Fix a crash when attempting to use bunyan -p on a platform without dtrace.

  • [issue #101] Fix a crash in bunyan rendering a record with unexpected "res.headers".

0.22.0

  • [issue #104] log.reopenFileStreams() convenience method to be used with external log rotation.

0.21.4

  • [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.

0.21.3

  • [issue #90] Fix bunyan -p '*' breakage in version 0.21.2.

0.21.2

Note: Bad release. The switchrate change below broke bunyan -p '*' usage (see issue #90). Use 0.21.3 or later.

  • [issue #88] Should be able to efficiently combine "-l" with "-p *".

  • Avoid DTrace buffer filling up, e.g. like this:

      $ bunyan -p 42241 > /tmp/all.log
      dtrace: error on enabled probe ID 3 (ID 75795: bunyan42241:mod-87ea640:log-trace:log-trace): out of scratch space in action #1 at DIF offset 12
      dtrace: error on enabled probe ID 3 (ID 75795: bunyan42241:mod-87ea640:log-trace:log-trace): out of scratch space in action #1 at DIF offset 12
      dtrace: 138 drops on CPU 4
      ...

    From Bryan: "the DTrace buffer is filling up because the string size is so large... by increasing the switchrate, you're increasing the rate at which that buffer is emptied."

0.21.1

  • [pull #83] Support rendering 'client_res' key in bunyan CLI (by github.com/mcavage).

0.21.0

  • 'make check' clean, 4-space indenting. No functional change here, just lots of code change.
  • [issue #80, #82] Drop assert that broke using 'rotating-file' with a default period (by github.com/ricardograca).

0.20.0

  • [Slight backward incompatibility] Fix serializer bug introduced in 0.18.3 (see below) to only apply serializers to log records when appropriate.

    This also makes a semantic change to custom serializers. Before this change a serializer function was called for a log record key when that value was truth-y. The semantic change is to call the serializer function as long as the value is not undefined. That means that a serializer function should handle falsey values such as false and null.

  • Update to latest 'mv' dep (required for rotating-file support) to support node v0.10.0.

0.19.0

WARNING: This release includes a bug introduced in bunyan 0.18.3 (see below). Please upgrade to bunyan 0.20.0.

  • [Slight backward incompatibility] Change the default error serialization (a.k.a. bunyan.stdSerializers.err) to not serialize all additional attributes of the given error object. This is an open door to unsafe logging and logging should always be safe. With this change, error serialization will log these attributes: message, name, stack, code, signal. The latter two are added because some core node APIs include those fields (e.g. child_process.exec).

    Concrete examples where this has hurt have been the "domain" change necessitating 0.18.3 and a case where node-restify uses an error object as the response object. When logging the err and res in the same log statement (common for restify audit logging), the res.body would be JSON stringified as '[Circular]' as it had already been emitted for the err key. This results in a WTF with the bunyan CLI because the err.body is not rendered.

    If you need the old behaviour back you will need to do this:

      var bunyan = require('bunyan');
      var errSkips = {
          // Skip domain keys. `domain` especially can have huge objects that can
          // OOM your app when trying to JSON.stringify.
          domain: true,
          domain_emitter: true,
          domain_bound: true,
          domain_thrown: true
      };
      bunyan.stdSerializers.err = function err(err) {
         if (!err || !err.stack)
             return err;
         var obj = {
             message: err.message,
             name: err.name,
             stack: getFullErrorStack(err)
         }
         Object.keys(err).forEach(function (k) {
             if (err[k] !== undefined && !errSkips[k]) {
                 obj[k] = err[k];
             }
         });
         return obj;
       };
  • "long" and "bunyan" output formats for the CLI. bunyan -o long is the default format, the same as before, just called "long" now instead of the cheesy "paul" name. The "bunyan" output format is the same as "json-0", just with a more convenient name.

0.18.3

WARNING: This release introduced a bug such that all serializers are applied to all log records even if the log record did not contain the key for that serializer. If a logger serializer function does not handle being given undefined, then you'll get warnings like this on stderr:

bunyan: ERROR: This should never happen. This is a bug in <https://github.com/trentm/node-bunyan> or in this application. Exception from "foo" Logger serializer: Error: ...
    at Object.bunyan.createLogger.serializers.foo (.../myapp.js:20:15)
    at Logger._applySerializers (.../lib/bunyan.js:644:46)
    at Array.forEach (native)
    at Logger._applySerializers (.../lib/bunyan.js:640:33)
    ...

and the following junk in written log records:

"foo":"(Error in Bunyan log "foo" serializer broke field. See stderr for details.)"

Please upgrade to bunyan 0.20.0.

  • Change the bunyan.stdSerializers.err serializer for errors to exclude the "domain*" keys. err.domain will include its assigned members which can arbitrarily large objects that are not intended for logging.

  • Make the "dtrace-provider" dependency optional. I hate to do this, but installing bunyan on Windows is made very difficult with this as a required dep. Even though "dtrace-provider" stubs out for non-dtrace-y platforms, without a compiler and Python around, node-gyp just falls over.

0.18.2

  • [pull #67] Remove debugging prints in rotating-file support. (by github.com/chad3814).
  • Update to dtrace-provider@0.2.7.

0.18.1

  • Get the bunyan CLI to not automatically page (i.e. pipe to less) if stdin isn't a TTY, or if following dtrace probe output (via -p PID), or if not given log file arguments.

0.18.0

  • Automatic paging support in the bunyan CLI (similar to git log et al). IOW, bunyan will open your pager (by default less) and pipe rendered log output through it. A main benefit of this is getting colored logs with a pager without the pain. Before you had to explicit use --color to tell bunyan to color output when the output was not a TTY:

      bunyan foo.log --color | less -R        # before
      bunyan foo.log                          # now

    Disable with the --no-pager option or the BUNYAN_NO_PAGER=1 environment variable.

    Limitations: Only supported for node >=0.8. Windows is not supported (at least not yet).

  • Switch test suite to nodeunit (still using a node-tap'ish API via a helper).

0.17.0

  • [issue #33] Log rotation support:

      var bunyan = require('bunyan');
      var log = bunyan.createLogger({
          name: 'myapp',
          streams: [{
              type: 'rotating-file',
              path: '/var/log/myapp.log',
              count: 7,
              period: 'daily'
          }]
      });
  • Tweak to CLI default pretty output: don't special case "latency" field. The special casing was perhaps nice, but less self-explanatory. Before:

      [2012-12-27T21:17:38.218Z]  INFO: audit/45769 on myserver: handled: 200 (15ms, audit=true, bar=baz)
        GET /foo
        ...

    After:

      [2012-12-27T21:17:38.218Z]  INFO: audit/45769 on myserver: handled: 200 (audit=true, bar=baz, latency=15)
        GET /foo
        ...
  • Exit CLI on EPIPE, otherwise we sit there useless processing a huge log file with, e.g. bunyan huge.log | head.

0.16.8

  • Guards on -c CONDITION usage to attempt to be more user friendly. Bogus JS code will result in this:

      $ bunyan portal.log -c 'this.req.username==boo@foo'
      bunyan: error: illegal CONDITION code: SyntaxError: Unexpected token ILLEGAL
        CONDITION script:
          Object.prototype.TRACE = 10;
          Object.prototype.DEBUG = 20;
          Object.prototype.INFO = 30;
          Object.prototype.WARN = 40;
          Object.prototype.ERROR = 50;
          Object.prototype.FATAL = 60;
          this.req.username==boo@foo
        Error:
          SyntaxError: Unexpected token ILLEGAL
              at new Script (vm.js:32:12)
              at Function.Script.createScript (vm.js:48:10)
              at parseArgv (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:465:27)
              at main (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:1252:16)
              at Object.<anonymous> (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:1330:3)
              at Module._compile (module.js:449:26)
              at Object.Module._extensions..js (module.js:467:10)
              at Module.load (module.js:356:32)
              at Function.Module._load (module.js:312:12)
              at Module.runMain (module.js:492:10)

    And all CONDITION scripts will be run against a minimal valid Bunyan log record to ensure they properly guard against undefined values (at least as much as can reasonably be checked). For example:

      $ bunyan portal.log -c 'this.req.username=="bob"'
      bunyan: error: CONDITION code cannot safely filter a minimal Bunyan log record
        CONDITION script:
          Object.prototype.TRACE = 10;
          Object.prototype.DEBUG = 20;
          Object.prototype.INFO = 30;
          Object.prototype.WARN = 40;
          Object.prototype.ERROR = 50;
          Object.prototype.FATAL = 60;
          this.req.username=="bob"
        Minimal Bunyan log record:
          {
            "v": 0,
            "level": 30,
            "name": "name",
            "hostname": "hostname",
            "pid": 123,
            "time": 1355514346206,
            "msg": "msg"
          }
        Filter error:
          TypeError: Cannot read property 'username' of undefined
              at bunyan-condition-0:7:9
              at Script.Object.keys.forEach.(anonymous function) [as runInNewContext] (vm.js:41:22)
              at parseArgv (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:477:18)
              at main (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:1252:16)
              at Object.<anonymous> (/Users/trentm/tm/node-bunyan-0.x/bin/bunyan:1330:3)
              at Module._compile (module.js:449:26)
              at Object.Module._extensions..js (module.js:467:10)
              at Module.load (module.js:356:32)
              at Function.Module._load (module.js:312:12)
              at Module.runMain (module.js:492:10)

    A proper way to do that condition would be:

      $ bunyan portal.log -c 'this.req && this.req.username=="bob"'

0.16.7

  • [issue #59] Clear a possibly interrupted ANSI color code on signal termination.

0.16.6

  • [issue #56] Support bunyan -p NAME to dtrace all PIDs matching 'NAME' in their command and args (using ps -A -o pid,command | grep NAME or, on SunOS pgrep -lf NAME). E.g.:

      bunyan -p myappname

    This is useful for usage of node's cluster module where you'll have multiple worker processes.

0.16.5

  • Allow bunyan -p '*' to capture bunyan dtrace probes from all processes.
  • issue #55: Add support for BUNYAN_NO_COLOR environment variable to turn off all output coloring. This is still overridden by the --color and --no-color options.

0.16.4

  • issue #54: Ensure (again, see 0.16.2) that stderr from the dtrace child process (when using bunyan -p PID) gets through. There had been a race between exiting bunyan and the flushing of the dtrace process' stderr.

0.16.3

0.16.2

  • Ensure that stderr from the dtrace child process (when using bunyan -p PID) gets through. The pipe usage wasn't working on SmartOS. This is important to show the user if they need to 'sudo'.

0.16.1

  • Ensure that a possible dtrace child process (with using bunyan -p PID) is terminated on signal termination of the bunyan CLI (at least for SIGINT, SIGQUIT, SIGTERM, SIGHUP).

0.16.0

  • Add bunyan -p PID support. This is a convenience wrapper that effectively calls:

      dtrace -x strsize=4k -qn 'bunyan$PID:::log-*{printf("%s", copyinstr(arg0))}' | bunyan

0.15.0

  • issue #48: Dtrace support! The elevator pitch is you can watch all logging from all Bunyan-using process with something like this:

      dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%d: %s: %s", pid, probefunc, copyinstr(arg0))}'

    And this can include log levels below what the service is actually configured to log. E.g. if the service is only logging at INFO level and you need to see DEBUG log messages, with this you can. Obviously this only works on dtrace-y platforms: Illumos derivatives of SunOS (e.g. SmartOS, OmniOS), Mac, FreeBSD.

    Or get the bunyan CLI to render logs nicely:

      dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%s", copyinstr(arg0))}' | bunyan

    See https://github.com/trentm/node-bunyan#dtrace-support for details. By Bryan Cantrill.

0.14.6

  • Export bunyan.safeCycles(). This may be useful for custom type == "raw" streams that may do JSON stringification of log records themselves. Usage:

      var str = JSON.stringify(rec, bunyan.safeCycles());
  • [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 Bunyan CLI crash message to make it easier to provide relevant details in a bug report.

0.14.5

  • Fix a bug in the long-stack-trace error serialization added in 0.14.4. The symptom:

      bunyan@0.14.4: .../node_modules/bunyan/lib/bunyan.js:1002
        var ret = ex.stack || ex.toString();
                    ^
      TypeError: Cannot read property 'stack' of undefined
          at getFullErrorStack (.../node_modules/bunyan/lib/bunyan.js:1002:15)
          ...

0.14.4

  • Bad release. Use 0.14.5 instead.
  • Improve error serialization to walk the chain of .cause() errors from the likes of WError or VError error classes from verror and restify v2.0. Example:

      [2012-10-11T00:30:21.871Z] ERROR: imgapi/99612 on 0525989e-2086-4270-b960-41dd661ebd7d: my-message
          ValidationFailedError: my-message; caused by TypeError: cause-error-message
              at Server.apiPing (/opt/smartdc/imgapi/lib/app.js:45:23)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.setupReq (/opt/smartdc/imgapi/lib/app.js:178:9)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.parseBody (/opt/smartdc/imgapi/node_modules/restify/lib/plugins/body_parser.js:15:33)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.parseQueryString (/opt/smartdc/imgapi/node_modules/restify/lib/plugins/query.js:40:25)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server._run (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:579:17)
              at Server._handle.log.trace.req (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:480:38)
          Caused by: TypeError: cause-error-message
              at Server.apiPing (/opt/smartdc/imgapi/lib/app.js:40:25)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.setupReq (/opt/smartdc/imgapi/lib/app.js:178:9)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.parseBody (/opt/smartdc/imgapi/node_modules/restify/lib/plugins/body_parser.js:15:33)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server.parseQueryString (/opt/smartdc/imgapi/node_modules/restify/lib/plugins/query.js:40:25)
              at next (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:550:50)
              at Server._run (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:579:17)
              at Server._handle.log.trace.req (/opt/smartdc/imgapi/node_modules/restify/lib/server.js:480:38)

0.14.2

  • [issue #45] Fix bunyan CLI (default output mode) to not crash on a 'res' field that isn't a response object, but a string.

0.14.1

  • [issue #44] Fix the default bunyan CLI output of a res.body that is an object instead of a string. See issue#38 for the same with req.body.

0.14.0

  • [pull #41] Safe JSON.stringifying of emitted log records to avoid blowing up on circular objects (by Isaac Schlueter).

0.13.5

  • [issue #39] Fix a bug with client_req handling in the default output of the bunyan CLI.

0.13.4

  • [issue #38] Fix the default bunyan CLI output of a req.body that is an object instead of a string.

0.13.3

  • Export bunyan.resolveLevel(NAME-OR-NUM) to resolve a level name or number to its log level number value:

      > bunyan.resolveLevel('INFO')
      30
      > bunyan.resolveLevel('debug')
      20

    A side-effect of this change is that the uppercase level name is now allowed in the logger constructor.

0.13.2

  • [issue #35] Ensure that an accidental log.info(BUFFER), where BUFFER is a node.js Buffer object, doesn't blow up.

0.13.1

  • [issue #34] Ensure req.body, res.body and other request/response fields are emitted by the bunyan CLI (mostly by Rob Gulewich).

0.13.0

  • [issue #31] Re-instate defines for the (uppercase) log level names (TRACE, DEBUG, etc.) in bunyan -c "..." filtering condition code. E.g.:

      $ ... | bunyan -c 'level >= ERROR'

0.12.0

  • [pull #32] bunyan -o short for more concise output (by Dave Pacheco). E.g.:

      22:56:52.856Z  INFO myservice: My message

    instead of:

      [2012-02-08T22:56:52.856Z]  INFO: myservice/123 on example.com: My message

0.11.3

  • Add '--strict' option to bunyan CLI to suppress all but legal Bunyan JSON log lines. By default non-JSON, and non-Bunyan lines are passed through.

0.11.2

  • [issue #30] Robust handling of 'req' field without a 'headers' subfield in bunyan CLI.
  • [issue #31] Pull the TRACE, DEBUG, et al defines from bunyan -c "..." filtering code. This was added in v0.11.1, but has a significant adverse affect.

0.11.1

  • Bad release. The TRACE et al names are bleeding into the log records when using '-c'.
  • Add defines for the (uppercase) log level names (TRACE, DEBUG, etc.) in bunyan -c "..." filtering condition code. E.g.:

      $ ... | bunyan -c 'level >= ERROR'

0.11.0

  • [pull #29] Add -l/--level for level filtering, and -c/--condition for arbitrary conditional filtering (by github.com/isaacs):

      $ ... | bunyan -l error   # filter out log records below error
      $ ... | bunyan -l 50      # numeric value works too
      $ ... | bunyan -c 'level===50'              # equiv with -c filtering
      $ ... | bunyan -c 'pid===123'               # filter on any field
      $ ... | bunyan -c 'pid===123' -c '_audit'   # multiple filters

0.10.0

  • [pull #24] Support for gzip'ed log files in the bunyan CLI (by github.com/mhart):

      $ bunyan foo.log.gz
      ...

0.9.0

  • [pull #16] Bullet proof the bunyan.stdSerializers (by github.com/rlidwka).

  • [pull #15] The bunyan CLI will now chronologically merge multiple log streams when it is given multiple file arguments. (by github.com/davepacheco)

      $ bunyan foo.log bar.log
      ... merged log records ...
  • [pull #15] A new bunyan.RingBuffer stream class that is useful for keeping the last N log messages in memory. This can be a fast way to keep recent, and thus hopefully relevant, log messages. (by @dapsays, github.com/davepacheco)

    Potential uses: Live debugging if a running process could inspect those messages. One could dump recent log messages at a finer log level than is typically logged on uncaughtException.

      var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
      var log = new bunyan({
          name: 'foo',
          streams: [{
              type: 'raw',
              stream: ringbuffer,
              level: 'debug'
          }]
      });
    
      log.info('hello world');
      console.log(ringbuffer.records);
  • Add support for "raw" streams. This is a logging stream that is given raw log record objects instead of a JSON-stringified string.

      function Collector() {
          this.records = [];
      }
      Collector.prototype.write = function (rec) {
          this.records.push(rec);
      }
      var log = new Logger({
          name: 'mylog',
          streams: [{
              type: 'raw',
              stream: new Collector()
          }]
      });

    See "examples/raw-stream.js". I expect raw streams to be useful for piping Bunyan logging to separate services (e.g. http://www.loggly.com/, https://github.com/etsy/statsd) or to separate in-process handling.

  • Add test/corpus/*.log files (accidentally excluded) so the test suite actually works(!).

0.8.0

  • [pull #21] Bunyan loggers now re-emit fs.createWriteStream error events. By github.com/EvanOxfeld. See "examples/handle-fs-error.js" and "test/error-event.js" for details.

      var log = new Logger({name: 'mylog', streams: [{path: FILENAME}]});
      log.on('error', function (err, stream) {
          // Handle error writing to or creating FILENAME.
      });
  • jsstyle'ing (via make check)

0.7.0

  • [issue #12] Add bunyan.createLogger(OPTIONS) form, as is more typical in node.js APIs. This'll eventually become the preferred form.

0.6.9

  • Change bunyan CLI default output to color "src" info red. Before the "src" information was uncolored. The "src" info is the filename, line number and function name resulting from using src: true in Logger creation. I.e., the (/Users/trentm/tm/node-bunyan/examples/hi.js:10) in:

      [2012-04-10T22:28:58.237Z]  INFO: myapp/39339 on banana.local (/Users/trentm/tm/node-bunyan/examples/hi.js:10): hi
  • Tweak bunyan CLI default output to still show an "err" field if it doesn't have a "stack" attribute.

0.6.8

  • Fix bad bug in log.child({...}, true); where the added child fields would be added to the parent's fields. This bug only existed for the "fast child" path (that second true argument). A side-effect of fixing this is that the "fast child" path is only 5 times as fast as the regular log.child, instead of 10 times faster.

0.6.7

  • [issue #6] Fix bleeding 'type' var to global namespace. (Thanks Mike!)

0.6.6

  • Add support to the bunyan CLI taking log file path args, bunyan foo.log, in addition to the usual cat foo.log | bunyan.
  • Improve reliability of the default output formatting of the bunyan CLI. Before it could blow up processing log records missing some expected fields.

0.6.5

  • ANSI coloring output from bunyan CLI tool (for the default output mode/style). Also add the '--color' option to force coloring if the output stream is not a TTY, e.g. cat my.log | bunyan --color | less -R. Use --no-color to disable coloring, e.g. if your terminal doesn't support ANSI codes.
  • Add 'level' field to log record before custom fields for that record. This just means that the raw record JSON will show the 'level' field earlier, which is a bit nicer for raw reading.

0.6.4

  • [issue #5] Fix log.info() -> boolean to work properly. Previous all were returning false. Ditto all trace/debug/.../fatal methods.

0.6.3

  • Allow an optional msg and arguments to the log.info(<Error> err) logging form. For example, before:

      log.debug(my_error_instance)            // good
      log.debug(my_error_instance, "boom!")   // wasn't allowed

    Now the latter is allowed if you want to expliciting set the log msg. Of course this applies to all the log.{trace|debug|info...}() methods.

  • bunyan cli output: clarify extra fields with quoting if empty or have spaces. E.g. 'cmd' and 'stderr' in the following:

      [2012-02-12T00:30:43.736Z] INFO: mo-docs/43194 on banana.local: buildDocs results (req_id=185edca2-2886-43dc-911c-fe41c09ec0f5, route=PutDocset, error=null, stderr="", cmd="make docs")

0.6.2

0.6.1

  • Internal: starting jsstyle usage.
  • Internal: add .npmignore. Previous packages had reams of bunyan crud in them.

0.6.0

  • Add 'pid' automatic log record field.

0.5.3

  • Add 'client_req' (HTTP client request) standard formatting in bunyan CLI default output.
  • Improve bunyan CLI default output to include all log record keys. Unknown keys are either included in the first line parenthetical (if short) or in the indented subsequent block (if long or multiline).

0.5.2

  • [issue #3] More type checking of new Logger(...) and log.child(...) options.
  • Start a test suite.

0.5.1

  • [issue #2] Add guard on JSON.stringifying of log records before emission. This will prevent log.info et al throwing on record fields that cannot be represented as JSON. An error will be printed on stderr and a clipped log record emitted with a 'bunyanMsg' key including error details. E.g.:

      bunyan: ERROR: could not stringify log record from /Users/trentm/tm/node-bunyan/examples/unstringifyable.js:12: TypeError: Converting circular structure to JSON
      {
        "name": "foo",
        "hostname": "banana.local",
        "bunyanMsg": "bunyan: ERROR: could not stringify log record from /Users/trentm/tm/node-bunyan/examples/unstringifyable.js:12: TypeError: Converting circular structure to JSON",
      ...

    Some timing shows this does effect log speed:

      $ node tools/timeguard.js     # before
      Time try/catch-guard on JSON.stringify:
       - log.info:  0.07365ms per iteration
      $ node tools/timeguard.js     # after
      Time try/catch-guard on JSON.stringify:
       - log.info:  0.07368ms per iteration

0.5.0

  • Use 10/20/... instead of 1/2/... for level constant values. Ostensibly this allows for intermediary levels from the defined "trace/debug/..." set. However, that is discouraged. I'd need a strong user argument to add support for easily using alternative levels. Consider using a separate JSON field instead.
  • s/service/name/ for Logger name field. "service" is unnecessarily tied to usage for a service. No need to differ from log4j Logger "name".
  • 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 example log.info(new TypeError("boom") will produce:

      ...
      "err": {
        "message": "boom",
        "name": "TypeError",
        "stack": "TypeError: boom\n    at Object.<anonymous> ..."
      },
      "msg": "boom",
      ...

0.4.0

  • Add new Logger({src: true}) config option to have a 'src' attribute be automatically added to log records with the log call source info. Example:

      "src": {
        "file": "/Users/trentm/tm/node-bunyan/examples/src.js",
        "line": 20,
        "func": "Wuzzle.woos"
      },

0.3.0

  • log.child(options[, simple]) Added simple boolean arg. Set true to assert that options only add fields (no config changes). Results in a 10x speed increase in child creation. See "tools/timechild.js". On my Mac, "fast child" creation takes about 0.001ms. IOW, if your app is dishing 10,000 req/s, then creating a log child for each request will take about 1% of the request time.
  • log.clone -> log.child to better reflect the relationship: streams and serializers are inherited. Streams can't be removed as part of the child creation. The child doesn't own the parent's streams (so can't close them).
  • Clean up Logger creation. The goal here was to ensure log.child usage is fast. TODO: measure that.
  • Add Logger.stdSerializers.err serializer which is necessary to get good Error object logging with node 0.6 (where core Error object properties are non-enumerable).

0.2.0

  • Spec'ing core/recommended log record fields.
  • Add LOG_VERSION to exports.
  • Improvements to request/response serializations.

0.1.0

First release.