From 9cd70479cb11a823c6c6e64e042f0d925de976d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionic=C4=83=20Biz=C4=83u?= Date: Fri, 10 Jul 2015 11:53:52 +0300 Subject: [PATCH] Added the missing syntax highlighting Added syntax highlighting everywhere and minor formatting. --- README.md | 687 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 384 insertions(+), 303 deletions(-) diff --git a/README.md b/README.md index 3ac25e3..fbc32de 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ 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"); +```js +var bunyan = require('bunyan'); +var log = bunyan.createLogger({name: "myapp"}); +log.info("hi"); +``` 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 - npm install bunyan +```sh +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` @@ -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 named after the logging levels: - $ cat hi.js - var bunyan = require('bunyan'); - var log = bunyan.createLogger({name: 'myapp'}); - log.info('hi'); - log.warn({lang: 'fr'}, 'au revoir'); +```sh +$ cat 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. @@ -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: "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} - +```sh +$ 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} +``` ## 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. +```js +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('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'); - // Adds "foo" field to log record. You can add any number - // of additional fields here. +log.info({foo: 'bar'}, 'hi'); + // Adds "foo" field to log record. You can add any number + // of additional fields here. - 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(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". +``` 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 @@ -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 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 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. `| bunyan -c 'this.foo == "bar"'`). Using our example above: - $ node hi.js | ./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) +```sh +$ node hi.js | ./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 @@ -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 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) +```sh +$ 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) +```sh +$ 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. @@ -153,32 +170,35 @@ See `bunyan --help` for other facilities. 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' - }); +```js +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 - } - ] - }); +```js +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](#streams) below. - ## log.child 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` field: - var bunyan = require('bunyan'); - var log = bunyan.createLogger({name: 'myapp'}); +```js +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.') - } +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'); +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} +```sh +$ 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 - +```sh +$ 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](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 includes a `req.log` logger that is: - log.child({req_id: }, true) +```js +log.child({req_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. @@ -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 JavaScript object**, so you can easily do the following: - log.info({req: }, 'something about handling this request'); +```js +log.info({req: }, 'something about handling this request'); +``` Serializers is a mapping of log record field name, "req" in this example, to a serializer function. That looks like this: - function reqSerializer(req) { - return { - method: req.method, - url: req.url, - headers: req.headers - } +```js +function reqSerializer(req) { + return { + method: req.method, + url: req.url, + headers: req.headers } - var log = bunyan.createLogger({ - name: 'myapp', - serializers: { - req: reqSerializer - } - }); +} +var log = bunyan.createLogger({ + name: 'myapp', + serializers: { + req: reqSerializer + } +}); +``` Or this: - var log = bunyan.createLogger({ - name: 'myapp', - serializers: {req: bunyan.stdSerializers.req} - }); +```js +var log = bunyan.createLogger({ + name: 'myapp', + serializers: {req: bunyan.stdSerializers.req} +}); +``` because Bunyan includes a small set of standard serializers. To use all the standard serializers you can use: - var log = bunyan.createLogger({ - ... - serializers: bunyan.stdSerializers - }); +```js +var log = bunyan.createLogger({ + ... + serializers: bunyan.stdSerializers +}); +``` **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 @@ -284,25 +319,29 @@ 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 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: - { - "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 - } +```js +{ + "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.** @@ -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: - 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.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.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 Record Fields @@ -368,30 +407,33 @@ 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} +```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: - { - "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 - } - +```js +{ + "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: @@ -432,6 +474,7 @@ Recommended/Best Practice Fields: - `err`: Object. A caught JS exception. Log that thing with `log.info(err)` to get: + ```js ... "err": { "message": "boom", @@ -440,6 +483,7 @@ Recommended/Best Practice Fields: }, "msg": "boom", ... + ``` Or use the `bunyan.stdSerializers.err` serializer in your Logger and 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` to serialize a request with a suggested set of keys. Example: + ```js { "method": "GET", "url": "/path?q=1#anchor", @@ -465,15 +510,17 @@ Recommended/Best Practice Fields: "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: + ```js { "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: @@ -494,26 +541,30 @@ 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" - }, - ... - ] - }); +```js +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 specified with the "stream" and "level" options (internally converted to a `Logger.streams`). - var log = bunyan.createLogger({ - name: "foo", - stream: process.stderr, - level: "debug" - }); +```js +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 @@ -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 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. - }); +```js +var log = bunyan.createLogger({name: 'mylog', streams: [{path: LOG_PATH}]}); +log.on('error', function (err, stream) { + // Handle stream write or create error here. +}); +``` Note: This is **not** that same as a log record at the "error" level as 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`, `process.stderr`. - var log = bunyan.createLogger({ - name: 'foo', - streams: [{ - stream: process.stderr - // `type: 'stream'` is implied - }] - }); +```js +var log = bunyan.createLogger({ + name: 'foo', + streams: [{ + stream: process.stderr + // `type: 'stream'` is implied + }] +}); +``` @@ -596,13 +651,15 @@ used for anything else. 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 - }] - }); +```js +var log = bunyan.createLogger({ + name: 'foo', + streams: [{ + path: '/var/log/foo.log', + // `type: 'file'` is implied + }] +}); +```
@@ -665,21 +722,25 @@ 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 - }] - }); +```js +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 +```sh +/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. @@ -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 app: - var log = bunyan.createLogger(...); - ... - process.on('SIGUSR2', function () { - log.reopenFileStreams(); - }); +```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 @@ -779,37 +842,40 @@ 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 - } - ] - }); +```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); +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 } ] - +```js +[ { name: 'foo', + hostname: '912d2b29', + pid: 50346, + level: 30, + msg: 'hello world', + time: '2012-06-19T21:34:19.906Z', + v: 0 } ] +``` ## 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`) that makes available the following probes: - log-trace - log-debug - log-info - log-warn - log-error - log-fatal +```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 @@ -861,86 +929,98 @@ 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))}' +```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: - 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: - 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: - 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: - bunyan -p 1234 - +```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!": - 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: - {"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 - 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 + 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 @@ -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 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 @@ -961,12 +1043,13 @@ script. 1. Get browserify and bunyan installed in your module: - - $ npm install browserify bunyan + ```sh + $ npm install browserify bunyan + ``` 2. An example script using Bunyan, "play.js": - ```javascript + ```js var bunyan = require('bunyan'); var log = bunyan.createLogger({name: 'play', level: 'debug'}); 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": - $ ./node_modules/.bin/browserify play.js -o play.browser.js + ```sh + $ ./node_modules/.bin/browserify play.js -o play.browser.js + ``` 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: - $ open play.html - + ```sh + $ open play.html + ``` Here is what it looks like in Firefox's console: ![Bunyan + Browserify in the 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 you'll want to add your own stream, starting with something like this: -```javascript +```js var bunyan = require('./lib/bunyan'); function MyRawStream() {} @@ -1031,9 +1117,6 @@ var log = bunyan.createLogger({ log.info('hi on info'); ``` - - - # Versioning The scheme I follow is most succinctly described by the bootstrap guys @@ -1043,12 +1126,10 @@ tl;dr: All versions are `..` which will be incremented for breaking backward compat and major reworks, new features without breaking change, and bug fixes, respectively. - # License MIT. See "LICENSE.txt". - # See Also - Bunyan syslog support: .