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
your 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:
```js
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 *Object*s 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:
```js
/* 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:
```js
[ { name: 'foo',
hostname: '912d2b29',
pid: 50346,
level: 30,
msg: 'hello world',
time: '2012-06-19T21:34:19.906Z',
v: 0 } ]
```
## third-party streams
(There are a lot that aren't listed here. `npm search bunyan` is a good
place to start.)
- syslog:
[mcavage/node-bunyan-syslog](https://github.com/mcavage/node-bunyan-syslog)
provides support for directing bunyan logging to a syslog server.
- bunyan-slack:
[qualitybath/bunyan-slack](https://github.com/qualitybath/bunyan-slack) Bunyan stream for Slack chat integration.
- bunyan-fogbugz
[qualitybath/bunyan-fogbugz](https://github.com/qualitybath/bunyan-fogbugz) Bunyan stream for sending automated crash reports to FogBugz
- bunyan-cloudwatch:
[mirkokiefer/bunyan-cloudwatch](https://github.com/mirkokiefer/bunyan-cloudwatch) Bunyan stream for sending logs to AWS CloudWatch.
- TODO: eventually https://github.com/trentm/node-bunyan-winston
# 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:
```sh
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.)
```sh
dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%d: %s: %s", pid, probefunc, copyinstr(arg0))}'
```
Trace all log messages coming from the "wuzzle" component:
```sh
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:
```sh
dtrace -x strsize=4k -n 'bunyan1234:::log-debug{@[copyinstr(arg0)] = count()}'
```
Have the bunyan CLI pretty-print the traced logs:
```sh
dtrace -x strsize=4k -qn 'bunyan1234:::log-*{printf("%s", copyinstr(arg0))}' | bunyan
```
A convenience handle has been made for this:
```sh
bunyan -p 1234
```
On systems that support the
[`jstack`](http://dtrace.org/blogs/dap/2012/04/25/profiling-node-js/) action
via a node.js helper, get a stack backtrace for any debug message that
includes the string "danger!":
```sh
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
```
# Browserify
As the [Browserify](http://browserify.org/) 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:
```html
```
As of version 1.1.0, node-bunyan supports being run via Browserify. The
default [stream](#streams) 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:
```sh
$ npm install browserify bunyan
```
2. An example script using Bunyan, "play.js":
```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":
```sh
$ ./node_modules/.bin/browserify play.js -o play.browser.js
```
4. Put that into an HTML file, "play.html":
```html