Added the missing syntax highlighting
Added syntax highlighting everywhere and minor formatting.
This commit is contained in:
parent
4f071a0a37
commit
9cd70479cb
1 changed files with 384 additions and 303 deletions
355
README.md
355
README.md
|
@ -1,8 +1,10 @@
|
||||||
Bunyan is **a simple and fast JSON logging library** for node.js services:
|
Bunyan is **a simple and fast JSON logging library** for node.js services:
|
||||||
|
|
||||||
var bunyan = require('bunyan');
|
```js
|
||||||
var log = bunyan.createLogger({name: "myapp"});
|
var bunyan = require('bunyan');
|
||||||
log.info("hi");
|
var log = bunyan.createLogger({name: "myapp"});
|
||||||
|
log.info("hi");
|
||||||
|
```
|
||||||
|
|
||||||
and **a `bunyan` CLI tool** for nicely viewing those logs:
|
and **a `bunyan` CLI tool** for nicely viewing those logs:
|
||||||
|
|
||||||
|
@ -31,7 +33,9 @@ browser](https://groups.google.com/forum/?fromgroups#!forum/bunyan-logging).
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
npm install bunyan
|
```sh
|
||||||
|
npm install bunyan
|
||||||
|
```
|
||||||
|
|
||||||
**Tip**: The `bunyan` CLI tool is written to be compatible (within reason) with
|
**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`
|
all versions of Bunyan logs. Therefore you might want to `npm install -g bunyan`
|
||||||
|
@ -60,11 +64,13 @@ node.js library usage of bunyan in your apps.
|
||||||
Like most logging libraries you create a Logger instance and call methods
|
Like most logging libraries you create a Logger instance and call methods
|
||||||
named after the logging levels:
|
named after the logging levels:
|
||||||
|
|
||||||
$ cat hi.js
|
```sh
|
||||||
var bunyan = require('bunyan');
|
$ cat hi.js
|
||||||
var log = bunyan.createLogger({name: 'myapp'});
|
var bunyan = require('bunyan');
|
||||||
log.info('hi');
|
var log = bunyan.createLogger({name: 'myapp'});
|
||||||
log.warn({lang: 'fr'}, 'au revoir');
|
log.info('hi');
|
||||||
|
log.warn({lang: 'fr'}, 'au revoir');
|
||||||
|
```
|
||||||
|
|
||||||
All loggers must provide a "name". This is somewhat akin to the log4j logger
|
All loggers must provide a "name". This is somewhat akin to the log4j logger
|
||||||
"name", but Bunyan doesn't do hierarchical logger names.
|
"name", but Bunyan doesn't do hierarchical logger names.
|
||||||
|
@ -72,33 +78,36 @@ All loggers must provide a "name". This is somewhat akin to the log4j logger
|
||||||
**Bunyan log records are JSON.** A few fields are added automatically:
|
**Bunyan log records are JSON.** A few fields are added automatically:
|
||||||
"pid", "hostname", "time" and "v".
|
"pid", "hostname", "time" and "v".
|
||||||
|
|
||||||
$ node hi.js
|
```sh
|
||||||
{"name":"myapp","hostname":"banana.local","pid":40161,"level":30,"msg":"hi","time":"2013-01-04T18:46:23.851Z","v":0}
|
$ node hi.js
|
||||||
{"name":"myapp","hostname":"banana.local","pid":40161,"level":40,"lang":"fr","msg":"au revoir","time":"2013-01-04T18:46:23.853Z","v":0}
|
{"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}
|
||||||
|
```
|
||||||
|
|
||||||
## Log Method API
|
## Log Method API
|
||||||
|
|
||||||
The example above shows two different ways to call `log.info(...)`. The
|
The example above shows two different ways to call `log.info(...)`. The
|
||||||
full API is:
|
full API is:
|
||||||
|
|
||||||
log.info(); // Returns a boolean: is the "info" level enabled?
|
```js
|
||||||
|
log.info(); // Returns a boolean: is the "info" level enabled?
|
||||||
// This is equivalent to `log.isInfoEnabled()` or
|
// This is equivalent to `log.isInfoEnabled()` or
|
||||||
// `log.isEnabledFor(INFO)` in log4j.
|
// `log.isEnabledFor(INFO)` in log4j.
|
||||||
|
|
||||||
log.info('hi'); // Log a simple string message (or number).
|
log.info('hi'); // Log a simple string message (or number).
|
||||||
log.info('hi %s', bob, anotherVar); // Uses `util.format` for msg formatting.
|
log.info('hi %s', bob, anotherVar); // Uses `util.format` for msg formatting.
|
||||||
|
|
||||||
log.info({foo: 'bar'}, 'hi');
|
log.info({foo: 'bar'}, 'hi');
|
||||||
// Adds "foo" field to log record. You can add any number
|
// Adds "foo" field to log record. You can add any number
|
||||||
// of additional fields here.
|
// of additional fields here.
|
||||||
|
|
||||||
log.info(err); // Special case to log an `Error` instance to the record.
|
log.info(err); // Special case to log an `Error` instance to the record.
|
||||||
// This adds an "err" field with exception details
|
// This adds an "err" field with exception details
|
||||||
// (including the stack) and sets "msg" to the exception
|
// (including the stack) and sets "msg" to the exception
|
||||||
// message.
|
// message.
|
||||||
log.info(err, 'more on this: %s', more);
|
log.info(err, 'more on this: %s', more);
|
||||||
// ... or you can specify the "msg".
|
// ... or you can specify the "msg".
|
||||||
|
```
|
||||||
|
|
||||||
Note that this implies **you cannot pass any object as the first argument
|
Note that this implies **you cannot pass any object as the first argument
|
||||||
to log it**. IOW, `log.info(mywidget)` may not be what you expect. Instead
|
to log it**. IOW, `log.info(mywidget)` may not be what you expect. Instead
|
||||||
|
@ -106,7 +115,9 @@ 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
|
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.:
|
practice to always give a field name to included objects, e.g.:
|
||||||
|
|
||||||
log.info({widget: mywidget}, ...)
|
```js
|
||||||
|
log.info({widget: mywidget}, ...)
|
||||||
|
```
|
||||||
|
|
||||||
This will dove-tail with [Bunyan serializer support](#serializers), discussed
|
This will dove-tail with [Bunyan serializer support](#serializers), discussed
|
||||||
later.
|
later.
|
||||||
|
@ -123,9 +134,11 @@ but not for reading directly. A **`bunyan` tool** is provided **for
|
||||||
pretty-printing bunyan logs** and for **filtering** (e.g.
|
pretty-printing bunyan logs** and for **filtering** (e.g.
|
||||||
`| bunyan -c 'this.foo == "bar"'`). Using our example above:
|
`| bunyan -c 'this.foo == "bar"'`). Using our example above:
|
||||||
|
|
||||||
$ node hi.js | ./bin/bunyan
|
```sh
|
||||||
[2013-01-04T19:01:18.241Z] INFO: myapp/40208 on banana.local: hi
|
$ node hi.js | ./bin/bunyan
|
||||||
[2013-01-04T19:01:18.242Z] WARN: myapp/40208 on banana.local: au revoir (lang=fr)
|
[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
|
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
|
log output. That example also shows the nice formatting automatically done for
|
||||||
|
@ -136,14 +149,18 @@ 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
|
for digging through large log files or for analysis. We can filter only
|
||||||
records above a certain level:
|
records above a certain level:
|
||||||
|
|
||||||
$ node hi.js | bunyan -l warn
|
```sh
|
||||||
[2013-01-04T19:08:37.182Z] WARN: myapp/40353 on banana.local: au revoir (lang=fr)
|
$ 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
|
Or filter on the JSON fields in the records (e.g. only showing the French
|
||||||
records in our contrived example):
|
records in our contrived example):
|
||||||
|
|
||||||
$ node hi.js | bunyan -c 'this.lang == "fr"'
|
```sh
|
||||||
[2013-01-04T19:08:26.411Z] WARN: myapp/40342 on banana.local: au revoir (lang=fr)
|
$ 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.
|
See `bunyan --help` for other facilities.
|
||||||
|
|
||||||
|
@ -153,16 +170,19 @@ See `bunyan --help` for other facilities.
|
||||||
By default, log output is to stdout and at the "info" level. Explicitly that
|
By default, log output is to stdout and at the "info" level. Explicitly that
|
||||||
looks like:
|
looks like:
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'myapp',
|
name: 'myapp',
|
||||||
stream: process.stdout,
|
stream: process.stdout,
|
||||||
level: 'info'
|
level: 'info'
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
That is an abbreviated form for a single stream. **You can define multiple
|
That is an abbreviated form for a single stream. **You can define multiple
|
||||||
streams at different levels**.
|
streams at different levels**.
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'myapp',
|
name: 'myapp',
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
|
@ -174,11 +194,11 @@ streams at different levels**.
|
||||||
path: '/var/tmp/myapp-error.log' // log ERROR and above to a file
|
path: '/var/tmp/myapp-error.log' // log ERROR and above to a file
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
More on streams in the [Streams section](#streams) below.
|
More on streams in the [Streams section](#streams) below.
|
||||||
|
|
||||||
|
|
||||||
## log.child
|
## log.child
|
||||||
|
|
||||||
Bunyan has a concept of a child logger to **specialize a logger for a
|
Bunyan has a concept of a child logger to **specialize a logger for a
|
||||||
|
@ -190,38 +210,43 @@ 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`
|
be exactly as on the parent logger with the addition of the `widget_type`
|
||||||
field:
|
field:
|
||||||
|
|
||||||
var bunyan = require('bunyan');
|
```js
|
||||||
var log = bunyan.createLogger({name: 'myapp'});
|
var bunyan = require('bunyan');
|
||||||
|
var log = bunyan.createLogger({name: 'myapp'});
|
||||||
|
|
||||||
function Wuzzle(options) {
|
function Wuzzle(options) {
|
||||||
this.log = options.log.child({widget_type: 'wuzzle'});
|
this.log = options.log.child({widget_type: 'wuzzle'});
|
||||||
this.log.info('creating a wuzzle')
|
this.log.info('creating a wuzzle')
|
||||||
}
|
}
|
||||||
Wuzzle.prototype.woos = function () {
|
Wuzzle.prototype.woos = function () {
|
||||||
this.log.warn('This wuzzle is woosey.')
|
this.log.warn('This wuzzle is woosey.')
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info('start');
|
log.info('start');
|
||||||
var wuzzle = new Wuzzle({log: log});
|
var wuzzle = new Wuzzle({log: log});
|
||||||
wuzzle.woos();
|
wuzzle.woos();
|
||||||
log.info('done');
|
log.info('done');
|
||||||
|
```
|
||||||
|
|
||||||
Running that looks like (raw):
|
Running that looks like (raw):
|
||||||
|
|
||||||
$ node myapp.js
|
```sh
|
||||||
{"name":"myapp","hostname":"myhost","pid":34572,"level":30,"msg":"start","time":"2013-01-04T07:47:25.814Z","v":0}
|
$ node myapp.js
|
||||||
{"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,"level":30,"msg":"start","time":"2013-01-04T07:47:25.814Z","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,"widget_type":"wuzzle","level":30,"msg":"creating a wuzzle","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}
|
{"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):
|
And with the `bunyan` CLI (using the "short" output mode):
|
||||||
|
|
||||||
$ node myapp.js | bunyan -o short
|
```sh
|
||||||
07:46:42.707Z INFO myapp: start
|
$ node myapp.js | bunyan -o short
|
||||||
07:46:42.709Z INFO myapp: creating a wuzzle (widget_type=wuzzle)
|
07:46:42.707Z INFO myapp: start
|
||||||
07:46:42.709Z WARN myapp: This wuzzle is woosey. (widget_type=wuzzle)
|
07:46:42.709Z INFO myapp: creating a wuzzle (widget_type=wuzzle)
|
||||||
07:46:42.709Z INFO myapp: done
|
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
|
A more practical example is in the
|
||||||
[node-restify](https://github.com/mcavage/node-restify) web framework.
|
[node-restify](https://github.com/mcavage/node-restify) web framework.
|
||||||
|
@ -229,7 +254,9 @@ Restify uses Bunyan for its logging. One feature of its integration, is that
|
||||||
if `server.use(restify.requestLogger())` is used, each restify request handler
|
if `server.use(restify.requestLogger())` is used, each restify request handler
|
||||||
includes a `req.log` logger that is:
|
includes a `req.log` logger that is:
|
||||||
|
|
||||||
log.child({req_id: <unique request id>}, true)
|
```js
|
||||||
|
log.child({req_id: <unique request id>}, true)
|
||||||
|
```
|
||||||
|
|
||||||
Apps using restify can then use `req.log` and have all such log records
|
Apps using restify can then use `req.log` and have all such log records
|
||||||
include the unique request id (as "req\_id"). Handy.
|
include the unique request id (as "req\_id"). Handy.
|
||||||
|
@ -240,39 +267,47 @@ include the unique request id (as "req\_id"). Handy.
|
||||||
Bunyan has a concept of **"serializers" to produce a JSON-able object from a
|
Bunyan has a concept of **"serializers" to produce a JSON-able object from a
|
||||||
JavaScript object**, so you can easily do the following:
|
JavaScript object**, so you can easily do the following:
|
||||||
|
|
||||||
log.info({req: <request object>}, 'something about handling this request');
|
```js
|
||||||
|
log.info({req: <request object>}, 'something about handling this request');
|
||||||
|
```
|
||||||
|
|
||||||
Serializers is a mapping of log record field name, "req" in this example, to
|
Serializers is a mapping of log record field name, "req" in this example, to
|
||||||
a serializer function. That looks like this:
|
a serializer function. That looks like this:
|
||||||
|
|
||||||
function reqSerializer(req) {
|
```js
|
||||||
|
function reqSerializer(req) {
|
||||||
return {
|
return {
|
||||||
method: req.method,
|
method: req.method,
|
||||||
url: req.url,
|
url: req.url,
|
||||||
headers: req.headers
|
headers: req.headers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var log = bunyan.createLogger({
|
var log = bunyan.createLogger({
|
||||||
name: 'myapp',
|
name: 'myapp',
|
||||||
serializers: {
|
serializers: {
|
||||||
req: reqSerializer
|
req: reqSerializer
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Or this:
|
Or this:
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'myapp',
|
name: 'myapp',
|
||||||
serializers: {req: bunyan.stdSerializers.req}
|
serializers: {req: bunyan.stdSerializers.req}
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
because Bunyan includes a small set of standard serializers. To use all the
|
because Bunyan includes a small set of standard serializers. To use all the
|
||||||
standard serializers you can use:
|
standard serializers you can use:
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
...
|
...
|
||||||
serializers: bunyan.stdSerializers
|
serializers: bunyan.stdSerializers
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
**Note**: Your own serializers should never throw, otherwise you'll get an
|
**Note**: Your own serializers should never throw, otherwise you'll get an
|
||||||
ugly message on stderr from Bunyan (along with the traceback) and the field
|
ugly message on stderr from Bunyan (along with the traceback) and the field
|
||||||
|
@ -284,11 +319,14 @@ in your log record will be replaced with a short error message.
|
||||||
The **source file, line and function of the log call site** can be added to
|
The **source file, line and function of the log call site** can be added to
|
||||||
log records by using the `src: true` config option:
|
log records by using the `src: true` config option:
|
||||||
|
|
||||||
var log = bunyan.createLogger({src: true, ...});
|
```js
|
||||||
|
var log = bunyan.createLogger({src: true, ...});
|
||||||
|
```
|
||||||
|
|
||||||
This adds the call source info with the 'src' field, like this:
|
This adds the call source info with the 'src' field, like this:
|
||||||
|
|
||||||
{
|
```js
|
||||||
|
{
|
||||||
"name": "src-example",
|
"name": "src-example",
|
||||||
"hostname": "banana.local",
|
"hostname": "banana.local",
|
||||||
"pid": 123,
|
"pid": 123,
|
||||||
|
@ -302,7 +340,8 @@ This adds the call source info with the 'src' field, like this:
|
||||||
"func": "Wuzzle.woos"
|
"func": "Wuzzle.woos"
|
||||||
},
|
},
|
||||||
"v": 0
|
"v": 0
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
**WARNING: Determining the call source info is slow. Never use this option
|
**WARNING: Determining the call source info is slow. Never use this option
|
||||||
in production.**
|
in production.**
|
||||||
|
@ -336,20 +375,20 @@ The lowercase level names are aliases supported in the API.
|
||||||
|
|
||||||
Here is the API for changing levels in an existing logger:
|
Here is the API for changing levels in an existing logger:
|
||||||
|
|
||||||
log.level() -> INFO // gets current level (lowest level of all streams)
|
```js
|
||||||
|
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.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
|
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
# Log Record Fields
|
# Log Record Fields
|
||||||
|
|
||||||
|
@ -368,11 +407,14 @@ incorrect signature) is always a bug in Bunyan.**
|
||||||
|
|
||||||
A typical Bunyan log record looks like this:
|
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}
|
```js
|
||||||
|
{"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:
|
Pretty-printed:
|
||||||
|
|
||||||
{
|
```js
|
||||||
|
{
|
||||||
"name": "myserver",
|
"name": "myserver",
|
||||||
"hostname": "banana.local",
|
"hostname": "banana.local",
|
||||||
"pid": 123,
|
"pid": 123,
|
||||||
|
@ -390,8 +432,8 @@ Pretty-printed:
|
||||||
"msg": "start request",
|
"msg": "start request",
|
||||||
"time": "2012-02-03T19:02:57.534Z",
|
"time": "2012-02-03T19:02:57.534Z",
|
||||||
"v": 0
|
"v": 0
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Core fields:
|
Core fields:
|
||||||
|
|
||||||
|
@ -432,6 +474,7 @@ Recommended/Best Practice Fields:
|
||||||
- `err`: Object. A caught JS exception. Log that thing with `log.info(err)`
|
- `err`: Object. A caught JS exception. Log that thing with `log.info(err)`
|
||||||
to get:
|
to get:
|
||||||
|
|
||||||
|
```js
|
||||||
...
|
...
|
||||||
"err": {
|
"err": {
|
||||||
"message": "boom",
|
"message": "boom",
|
||||||
|
@ -440,6 +483,7 @@ Recommended/Best Practice Fields:
|
||||||
},
|
},
|
||||||
"msg": "boom",
|
"msg": "boom",
|
||||||
...
|
...
|
||||||
|
```
|
||||||
|
|
||||||
Or use the `bunyan.stdSerializers.err` serializer in your Logger and
|
Or use the `bunyan.stdSerializers.err` serializer in your Logger and
|
||||||
do this `log.error({err: err}, "oops")`. See "examples/err.js".
|
do this `log.error({err: err}, "oops")`. See "examples/err.js".
|
||||||
|
@ -455,6 +499,7 @@ Recommended/Best Practice Fields:
|
||||||
- `req`: An HTTP server request. Bunyan provides `bunyan.stdSerializers.req`
|
- `req`: An HTTP server request. Bunyan provides `bunyan.stdSerializers.req`
|
||||||
to serialize a request with a suggested set of keys. Example:
|
to serialize a request with a suggested set of keys. Example:
|
||||||
|
|
||||||
|
```js
|
||||||
{
|
{
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"url": "/path?q=1#anchor",
|
"url": "/path?q=1#anchor",
|
||||||
|
@ -465,15 +510,17 @@ Recommended/Best Practice Fields:
|
||||||
"remoteAddress": "120.0.0.1",
|
"remoteAddress": "120.0.0.1",
|
||||||
"remotePort": 51244
|
"remotePort": 51244
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- `res`: An HTTP server response. Bunyan provides `bunyan.stdSerializers.res`
|
- `res`: An HTTP server response. Bunyan provides `bunyan.stdSerializers.res`
|
||||||
to serialize a response with a suggested set of keys. Example:
|
to serialize a response with a suggested set of keys. Example:
|
||||||
|
|
||||||
|
```js
|
||||||
{
|
{
|
||||||
"statusCode": 200,
|
"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"
|
"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:
|
Other fields to consider:
|
||||||
|
|
||||||
|
@ -494,8 +541,9 @@ interface, but there are some additional attributes used to create and
|
||||||
manage the stream. A Bunyan Logger instance has one or more streams.
|
manage the stream. A Bunyan Logger instance has one or more streams.
|
||||||
In general streams are specified with the "streams" option:
|
In general streams are specified with the "streams" option:
|
||||||
|
|
||||||
var bunyan = require('bunyan');
|
```js
|
||||||
var log = bunyan.createLogger({
|
var bunyan = require('bunyan');
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: "foo",
|
name: "foo",
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
|
@ -504,16 +552,19 @@ In general streams are specified with the "streams" option:
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
For convenience, if there is only one stream, it can specified with the
|
For convenience, if there is only one stream, it can specified with the
|
||||||
"stream" and "level" options (internally converted to a `Logger.streams`).
|
"stream" and "level" options (internally converted to a `Logger.streams`).
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: "foo",
|
name: "foo",
|
||||||
stream: process.stderr,
|
stream: process.stderr,
|
||||||
level: "debug"
|
level: "debug"
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Note that "file" streams do not support this shortcut (partly for historical
|
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
|
reasons and partly to not make it difficult to add a literal "path" field
|
||||||
|
@ -528,10 +579,12 @@ type "stream" emitting to `process.stdout` at the "info" level.
|
||||||
Bunyan re-emits error events from the created `WriteStream`. So you can
|
Bunyan re-emits error events from the created `WriteStream`. So you can
|
||||||
do this:
|
do this:
|
||||||
|
|
||||||
var log = bunyan.createLogger({name: 'mylog', streams: [{path: LOG_PATH}]});
|
```js
|
||||||
log.on('error', function (err, stream) {
|
var log = bunyan.createLogger({name: 'mylog', streams: [{path: LOG_PATH}]});
|
||||||
|
log.on('error', function (err, stream) {
|
||||||
// Handle stream write or create error here.
|
// Handle stream write or create error here.
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Note: This is **not** that same as a log record at the "error" level as
|
Note: This is **not** that same as a log record at the "error" level as
|
||||||
produced by `log.error(...)`.
|
produced by `log.error(...)`.
|
||||||
|
@ -544,13 +597,15 @@ Stream](http://nodejs.org/docs/latest/api/all.html#writable_Stream). A
|
||||||
"stream" (the writable stream) field is required. E.g.: `process.stdout`,
|
"stream" (the writable stream) field is required. E.g.: `process.stdout`,
|
||||||
`process.stderr`.
|
`process.stderr`.
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
streams: [{
|
streams: [{
|
||||||
stream: process.stderr
|
stream: process.stderr
|
||||||
// `type: 'stream'` is implied
|
// `type: 'stream'` is implied
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -596,13 +651,15 @@ used for anything else.</td>
|
||||||
A `type === 'file'` stream requires a "path" field. Bunyan will open this
|
A `type === 'file'` stream requires a "path" field. Bunyan will open this
|
||||||
file for appending. E.g.:
|
file for appending. E.g.:
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
streams: [{
|
streams: [{
|
||||||
path: '/var/log/foo.log',
|
path: '/var/log/foo.log',
|
||||||
// `type: 'file'` is implied
|
// `type: 'file'` is implied
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -665,7 +722,8 @@ for details.
|
||||||
A `type === 'rotating-file'` is a file stream that handles file automatic
|
A `type === 'rotating-file'` is a file stream that handles file automatic
|
||||||
rotation.
|
rotation.
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
```js
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
streams: [{
|
streams: [{
|
||||||
type: 'rotating-file',
|
type: 'rotating-file',
|
||||||
|
@ -673,13 +731,16 @@ rotation.
|
||||||
period: '1d', // daily rotation
|
period: '1d', // daily rotation
|
||||||
count: 3 // keep 3 back copies
|
count: 3 // keep 3 back copies
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
This will rotate '/var/log/foo.log' every day (at midnight) to:
|
This will rotate '/var/log/foo.log' every day (at midnight) to:
|
||||||
|
|
||||||
/var/log/foo.log.0 # yesterday
|
```sh
|
||||||
/var/log/foo.log.1 # 1 day ago
|
/var/log/foo.log.0 # yesterday
|
||||||
/var/log/foo.log.2 # 2 days ago
|
/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
|
*Currently*, there is no support for providing a template for the rotated
|
||||||
files, or for rotating when the log reaches a threshold size.
|
files, or for rotating when the log reaches a threshold size.
|
||||||
|
@ -749,11 +810,13 @@ 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
|
You can tell bunyan to reopen the file stream with code like this in your
|
||||||
app:
|
app:
|
||||||
|
|
||||||
var log = bunyan.createLogger(...);
|
```js
|
||||||
...
|
var log = bunyan.createLogger(...);
|
||||||
process.on('SIGUSR2', function () {
|
...
|
||||||
|
process.on('SIGUSR2', function () {
|
||||||
log.reopenFileStreams();
|
log.reopenFileStreams();
|
||||||
});
|
});
|
||||||
|
```
|
||||||
|
|
||||||
where you'd configure your log rotation to send SIGUSR2 (or some other signal)
|
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
|
to your process. Any other mechanism to signal your app to run
|
||||||
|
@ -779,10 +842,11 @@ own HTTP interface, or a post-mortem facility like MDB or node-panic.
|
||||||
|
|
||||||
To use a RingBuffer:
|
To use a RingBuffer:
|
||||||
|
|
||||||
/* Create a ring buffer that stores the last 100 records. */
|
```js
|
||||||
var bunyan = require('bunyan');
|
/* Create a ring buffer that stores the last 100 records. */
|
||||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
var bunyan = require('bunyan');
|
||||||
var log = bunyan.createLogger({
|
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||||
|
var log = bunyan.createLogger({
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
|
@ -795,21 +859,23 @@ To use a RingBuffer:
|
||||||
stream: ringbuffer
|
stream: ringbuffer
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info('hello world');
|
log.info('hello world');
|
||||||
console.log(ringbuffer.records);
|
console.log(ringbuffer.records);
|
||||||
|
```
|
||||||
|
|
||||||
This example emits:
|
This example emits:
|
||||||
|
|
||||||
[ { name: 'foo',
|
```js
|
||||||
|
[ { name: 'foo',
|
||||||
hostname: '912d2b29',
|
hostname: '912d2b29',
|
||||||
pid: 50346,
|
pid: 50346,
|
||||||
level: 30,
|
level: 30,
|
||||||
msg: 'hello world',
|
msg: 'hello world',
|
||||||
time: '2012-06-19T21:34:19.906Z',
|
time: '2012-06-19T21:34:19.906Z',
|
||||||
v: 0 } ]
|
v: 0 } ]
|
||||||
|
```
|
||||||
|
|
||||||
## third-party streams
|
## third-party streams
|
||||||
|
|
||||||
|
@ -842,12 +908,14 @@ On systems that support DTrace (e.g., MacOS, FreeBSD, illumos derivatives
|
||||||
like SmartOS and OmniOS), Bunyan will create a DTrace provider (`bunyan`)
|
like SmartOS and OmniOS), Bunyan will create a DTrace provider (`bunyan`)
|
||||||
that makes available the following probes:
|
that makes available the following probes:
|
||||||
|
|
||||||
log-trace
|
```sh
|
||||||
log-debug
|
log-trace
|
||||||
log-info
|
log-debug
|
||||||
log-warn
|
log-info
|
||||||
log-error
|
log-warn
|
||||||
log-fatal
|
log-error
|
||||||
|
log-fatal
|
||||||
|
```
|
||||||
|
|
||||||
Each of these probes has a single argument: the string that would be
|
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
|
written to the log. Note that when a probe is enabled, it will
|
||||||
|
@ -861,35 +929,47 @@ 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
|
(The `-x strsize=4k` is to raise dtrace's default 256 byte buffer size
|
||||||
because log messages are longer than typical dtrace probes.)
|
because log messages are longer than typical dtrace probes.)
|
||||||
|
|
||||||
dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%d: %s: %s", pid, probefunc, copyinstr(arg0))}'
|
```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:
|
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)}'
|
```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:
|
Aggregate debug messages from process 1234, by message:
|
||||||
|
|
||||||
dtrace -x strsize=4k -n 'bunyan1234:::log-debug{@[copyinstr(arg0)] = count()}'
|
```sh
|
||||||
|
dtrace -x strsize=4k -n 'bunyan1234:::log-debug{@[copyinstr(arg0)] = count()}'
|
||||||
|
```
|
||||||
|
|
||||||
Have the bunyan CLI pretty-print the traced logs:
|
Have the bunyan CLI pretty-print the traced logs:
|
||||||
|
|
||||||
dtrace -x strsize=4k -qn 'bunyan1234:::log-*{printf("%s", copyinstr(arg0))}' | bunyan
|
```sh
|
||||||
|
dtrace -x strsize=4k -qn 'bunyan1234:::log-*{printf("%s", copyinstr(arg0))}' | bunyan
|
||||||
|
```
|
||||||
|
|
||||||
A convenience handle has been made for this:
|
A convenience handle has been made for this:
|
||||||
|
|
||||||
bunyan -p 1234
|
```sh
|
||||||
|
bunyan -p 1234
|
||||||
|
```
|
||||||
|
|
||||||
On systems that support the
|
On systems that support the
|
||||||
[`jstack`](http://dtrace.org/blogs/dap/2012/04/25/profiling-node-js/) action
|
[`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
|
via a node.js helper, get a stack backtrace for any debug message that
|
||||||
includes the string "danger!":
|
includes the string "danger!":
|
||||||
|
|
||||||
dtrace -x strsize=4k -qn 'log-debug/strstr(copyinstr(arg0), "danger!") != NULL/{printf("\n%s", copyinstr(arg0)); jstack()}'
|
```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:
|
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}
|
```
|
||||||
|
{"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
|
node`0x87e2010
|
||||||
DTraceProviderBindings.node`usdt_fire_probe+0x32
|
DTraceProviderBindings.node`usdt_fire_probe+0x32
|
||||||
|
@ -940,7 +1020,7 @@ Output of the above might be:
|
||||||
node`_ZN4node5StartEiPPc+0x1d0
|
node`_ZN4node5StartEiPPc+0x1d0
|
||||||
node`main+0x1b
|
node`main+0x1b
|
||||||
node`_start+0x83
|
node`_start+0x83
|
||||||
|
```
|
||||||
|
|
||||||
# Browserify
|
# Browserify
|
||||||
|
|
||||||
|
@ -950,7 +1030,9 @@ 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
|
all its node.js dependencies into a single file that is runnable in the
|
||||||
browser via:
|
browser via:
|
||||||
|
|
||||||
<script src="play.browser.js"></script>
|
```html
|
||||||
|
<script src="play.browser.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
As of version 1.1.0, node-bunyan supports being run via Browserify. The
|
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
|
default [stream](#streams) when running in the browser is one that emits
|
||||||
|
@ -961,12 +1043,13 @@ script.
|
||||||
|
|
||||||
1. Get browserify and bunyan installed in your module:
|
1. Get browserify and bunyan installed in your module:
|
||||||
|
|
||||||
|
```sh
|
||||||
$ npm install browserify bunyan
|
$ npm install browserify bunyan
|
||||||
|
```
|
||||||
|
|
||||||
2. An example script using Bunyan, "play.js":
|
2. An example script using Bunyan, "play.js":
|
||||||
|
|
||||||
```javascript
|
```js
|
||||||
var bunyan = require('bunyan');
|
var bunyan = require('bunyan');
|
||||||
var log = bunyan.createLogger({name: 'play', level: 'debug'});
|
var log = bunyan.createLogger({name: 'play', level: 'debug'});
|
||||||
log.trace('this one does not emit');
|
log.trace('this one does not emit');
|
||||||
|
@ -978,7 +1061,9 @@ script.
|
||||||
|
|
||||||
3. Build this into a bundle to run in the browser, "play.browser.js":
|
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
|
$ ./node_modules/.bin/browserify play.js -o play.browser.js
|
||||||
|
```
|
||||||
|
|
||||||
4. Put that into an HTML file, "play.html":
|
4. Put that into an HTML file, "play.html":
|
||||||
|
|
||||||
|
@ -997,8 +1082,9 @@ script.
|
||||||
|
|
||||||
5. Open that in your browser and open your browser console:
|
5. Open that in your browser and open your browser console:
|
||||||
|
|
||||||
|
```sh
|
||||||
$ open play.html
|
$ open play.html
|
||||||
|
```
|
||||||
|
|
||||||
Here is what it looks like in Firefox's console: ![Bunyan + Browserify in the
|
Here is what it looks like in Firefox's console: ![Bunyan + Browserify in the
|
||||||
Firefox console](./docs/img/bunyan.browserify.png)
|
Firefox console](./docs/img/bunyan.browserify.png)
|
||||||
|
@ -1006,7 +1092,7 @@ Firefox console](./docs/img/bunyan.browserify.png)
|
||||||
For some, the raw log records might not be desired. To have a rendered log line
|
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:
|
you'll want to add your own stream, starting with something like this:
|
||||||
|
|
||||||
```javascript
|
```js
|
||||||
var bunyan = require('./lib/bunyan');
|
var bunyan = require('./lib/bunyan');
|
||||||
|
|
||||||
function MyRawStream() {}
|
function MyRawStream() {}
|
||||||
|
@ -1031,9 +1117,6 @@ var log = bunyan.createLogger({
|
||||||
log.info('hi on info');
|
log.info('hi on info');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Versioning
|
# Versioning
|
||||||
|
|
||||||
The scheme I follow is most succinctly described by the bootstrap guys
|
The scheme I follow is most succinctly described by the bootstrap guys
|
||||||
|
@ -1043,12 +1126,10 @@ tl;dr: All versions are `<major>.<minor>.<patch>` which will be incremented for
|
||||||
breaking backward compat and major reworks, new features without breaking
|
breaking backward compat and major reworks, new features without breaking
|
||||||
change, and bug fixes, respectively.
|
change, and bug fixes, respectively.
|
||||||
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
MIT. See "LICENSE.txt".
|
MIT. See "LICENSE.txt".
|
||||||
|
|
||||||
|
|
||||||
# See Also
|
# See Also
|
||||||
|
|
||||||
- Bunyan syslog support: <https://github.com/mcavage/node-bunyan-syslog>.
|
- Bunyan syslog support: <https://github.com/mcavage/node-bunyan-syslog>.
|
||||||
|
|
Loading…
Reference in a new issue