http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/bunyan/CONTRIBUTING.md ---------------------------------------------------------------------- diff --git a/node_modules/bunyan/CONTRIBUTING.md b/node_modules/bunyan/CONTRIBUTING.md new file mode 100644 index 0000000..628c7c2 --- /dev/null +++ b/node_modules/bunyan/CONTRIBUTING.md @@ -0,0 +1,205 @@ +# Contributing to node-bunyan + +Thanks for using node-bunyan and for considering contributing to it! Or perhaps +you are just here to get a sniff for what is going on with node-bunyan +development. + + +## How you can help + +If you want to help me here, great! Thank you! Some ideas: + +- Do you have experience with and/or recommendations for a good automated + testing service? Ideally I'd like support for Mac, Linux, SmartOS, and maybe + Windows. Also, support for node.js versions 0.10 up to whatever the current + latest is. Are those too tall an order? What's more, Bunyan is meant to work + (at least partially) in the browser. Is there a good service for that? + Please discuss on [issue #342](https://github.com/trentm/node-bunyan/issues/342). + +- Fielding issues labelled with "[Type-Question][Type-Question]", if you are familiar + with Bunyan and know how to answer them, would be great. + +- If you want to dive into code, but aren't *that* familiar with node-bunyan, + then [issues labelled with Experience-Easy][Experience-Easy] are a good + place to start. + +- [Once I've made a once over + triaging](https://github.com/trentm/node-bunyan/issues/335) and consolodating + issues and PRs, volunteering for issues in a particular + [component](#component) with which you have familiarity would be great. + +[Type-Question]: https://github.com/trentm/node-bunyan/issues?q=is%3Aopen+is%3Aissue+label%3AType-Question + + +## Trent's Biased Rules for Code + +In the hope that it makes it easier to get PRs into Bunyan, here is my biased +list of what I typically want. Submitting a PR without all of these is +*totally fine*! The only side-effect is that it may take longer for me to +provide feedback on it and merge it. I'll politely request missing pieces. + + +- Please follow existing code style. Contributed code must pass `make check`. + (Note: I intended to [change to eslint + soon](https://github.com/trentm/node-bunyan/issues/341), so currently `make + check` might be a moving target.) + +- Any user visible change in behaviour should almost certainly include an + update to the docs. Currently the "docs" is the README.md. + +- Adding a test case for code changes is **stronly recommended**, else I + can't easily promise to not break your fix/feature later. If you don't + grok the test suite, please ask. We can use it to form the basis for a + "test/README.md". + +- Typically a code change should have an associated issue or PR. This allows + addition of follow-up issues, discussion, test data, etc. to be associated + with the commit. Just using GitHub pull requests makes this easy. + +- All but the most trivial code changes should have an addition to the + [changelog](./CHANGES.md). The audience for the changelog is *Bunyan users*. + However, because rebasing longer-lived PRs against master is a pain + with a change to CHANGES.md, please **do not include a CHANGES.md change + in your PR. Instead suggest a CHANGES.md addition in a comment on the + PR.** + +- Good commit messages, please: + - The first line should be a succinct summary of the issue or fix. A + good candidate is to just cut 'n paste the issue title, if there is one. + - If the commit is for a particular issue/PR (see previous rule), please + list the issue number in the commit message. E.g. "Fixes #123" or "Related + to #234". + - The audience for commit messages is *Bunyan developers*. + + +## Pull Request Lifecycle + +(Language adapted from +[terraform](https://github.com/hashicorp/terraform/blob/master/CONTRIBUTING.md).) + +- You are welcome to submit your pull request for commentary or review before it + is fully completed. Please prefix the title of your pull request with "[WIP]" + to indicate this. It's also a good idea to include specific questions or items + you'd like feedback on. + +- Once you believe your pull request is ready to be merged, you can remove any + "[WIP]" prefix from the title and a core team member will review. See + Trent's Biased Rules above to help ensure that your contribution will be + merged quickly. + +- Trent or, if things go well, a node-bunyan maintainer will look over your + contribution and either provide comments letting you know if there is anything + left to do. Please be patient. Unfortunately, I'm not able to carve out + a *lot* of time for Bunyan development and maintenance. + +- Once all outstanding comments and checklist items have been addressed, your + contribution will be merged. Merged PRs will be included in the next + node-bunyan release. + +- In some cases, we might decide that a PR should be closed. We'll make sure to + provide clear reasoning when this happens. + + +## Issue labels + +The point of issue labeling for node-bunyan is to help answer "what should be +worked on now? what can be left for later?" I don't want issue labelling to +become a burden for anyone, so (a) don't feel obliged to add them yourself and +(b) I'm happy to reevaluate their usage. + +Bunyan shall have categories of [issue +labels](https://github.com/trentm/node-bunyan/labels) named "$category-$value". +An issue should have max *one* label from each set. Users of Google Code's +dearly departed issue tracker may remember this kind of thing. This is a +poorman's version of structured issue tracker metadata. + +I'm inclined to *not* do priorities right now. *Possibly* we'll use GitHub +milestones to basically set targets for upcoming releases. But otherwise my +sense is that for smaller OSS projects, assigning prios will get in the way. +If people would think it helpful, I'd consider "Difficulty-" or "Experience-" +categories (a la Rust's "E-" labels) to mark easier and intermediate tasks +that someone interested but maybe not very familiar with Bunyan might want +to tackle. + +For now, here are the various labels and their purpose: + +### Meta + +- needstriage: Temporary label to help me do a single triage pass through all + current open issues and PRs. + See [#335](https://github.com/trentm/node-bunyan/issues/335) + where I'm working through this. + +### Type + +Color: green + +- Type-Unknown: If it is still unclear or undecided if an issue is an intended + feature (perhaps arguing for better docs or examples to avoid confusion) or a + bug, I will use this category. +- Type-Question: Asking a question on Bunyan usage, about the project, etc. +- Type-Bug: A bug in Bunyan's behaviour. +- Type-Improvement: A new feature or other improvement. +- Type-Doc: Issues with Bunyan's documentation. +- Type-Task: A project task to be done. + +TODO: consider Type-Unknown for the "unclear if bug or feature" tickets. + +### Component + +Color: blue + +- Component-Project: Project meta stuff like testing, linting, build, install, + etc. +- Component-CLI: The `bunyan` command-line tool. +- Component-Lib: catch-all for other library stuff + - Component-LibRotation: The bunyan library's log rotation support. + - Component-LibBrowser: Bunyan's handling/support for running in the browser. + - Component-LibFlush: A separate component for collecting the tickets related + to closing/flushing bunyan streams on process shutdown. + +The point of components is to find like issues to help with reference, search +and resolving them. If no component fits an issue/PR, then don't add a label. + +### Resolution + +Color: red + +- Resolution-WontFix +- Resolution-Duplicate +- Resolution-Fixed: Also used to indicate "doc written", "question answered", + "feature implemented". +- Resolution-CannotRepro: After some reasonable attempt by maintainers to + reproduce a bug report, I want it to be non-controversial to close it + and mark it with this. If given more info by someone able to repro, we + can happy re-open issues. + +### Experience + +Color: yellow + +- Experience-Easy: Relatively little experience with node-bunyan should be + required to complete this issue. +- Experience-NeedsTest: Typically added to an issue or PR that needs a test + case. Someone familiar enough with node-bunyan's test suite could tackle this. +- Experience-Hard: At a guess, this is a thorny issue that requires known + node-bunyan well, knowing node.js well, requires design review or all of + these. + +One of the "Experience-\*" labels can optionally be put on an issue or PR to +indicate what kind of experience a contributor would need with node-bunyan +(and/or node.js) to complete it. For example, if you're looking for somewhere to +start, check out the [Experience-Easy][Experience-Easy] tag. This category idea +is borrowed from [rust's E-\* labels][rust-issue-triage]. + +[Experience-Easy]: https://github.com/trentm/node-bunyan/issues?q=is%3Aopen+is%3Aissue+label%3AExperience-Easy +[rust-issue-triage]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage + + +## Acknowledgements + +Anything good about this document is thanks to inspiration from +[rust](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) and, more +recently +[terraform](https://github.com/hashicorp/terraform/blob/master/CONTRIBUTING.md). +Anything bad about it, is my fault.
http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/bunyan/LICENSE.txt ---------------------------------------------------------------------- diff --git a/node_modules/bunyan/LICENSE.txt b/node_modules/bunyan/LICENSE.txt new file mode 100644 index 0000000..ced38b4 --- /dev/null +++ b/node_modules/bunyan/LICENSE.txt @@ -0,0 +1,24 @@ +# This is the MIT license + +Copyright 2016 Trent Mick +Copyright 2016 Joyent Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/bunyan/Makefile ---------------------------------------------------------------------- diff --git a/node_modules/bunyan/Makefile b/node_modules/bunyan/Makefile new file mode 100644 index 0000000..2eb3fd1 --- /dev/null +++ b/node_modules/bunyan/Makefile @@ -0,0 +1,149 @@ + +#---- Tools + +NODEUNIT := ./node_modules/.bin/nodeunit +SUDO := sudo +ifeq ($(shell uname -s),SunOS) + # On SunOS (e.g. SmartOS) we expect to run the test suite as the + # root user -- necessary to run dtrace. Therefore `pfexec` isn't + # necessary. + SUDO := +endif +DTRACE_UP_IN_HERE= +ifeq ($(shell uname -s),SunOS) + DTRACE_UP_IN_HERE=1 +endif +ifeq ($(shell uname -s),Darwin) + DTRACE_UP_IN_HERE=1 +endif +NODEOPT ?= $(HOME)/opt + + +#---- Files + +JSSTYLE_FILES := $(shell find lib test tools examples -name "*.js") bin/bunyan +# All test files *except* dtrace.test.js. +NON_DTRACE_TEST_FILES := $(shell ls -1 test/*.test.js | grep -v dtrace | xargs) + + +#---- Targets + +all $(NODEUNIT): + npm install $(NPM_INSTALL_FLAGS) + +# Ensure all version-carrying files have the same version. +.PHONY: versioncheck +versioncheck: + @echo version is: $(shell cat package.json | json version) + [[ `cat package.json | json version` == `grep '^## ' CHANGES.md | head -2 | tail -1 | awk '{print $$2}'` ]] + [[ `cat package.json | json version` == `grep '^var VERSION' bin/bunyan | awk -F"'" '{print $$2}'` ]] + [[ `cat package.json | json version` == `grep '^var VERSION' lib/bunyan.js | awk -F"'" '{print $$2}'` ]] + @echo Version check ok. + +.PHONY: cutarelease +cutarelease: check + [[ -z `git status --short` ]] # If this fails, the working dir is dirty. + @which json 2>/dev/null 1>/dev/null && \ + ver=$(shell json -f package.json version) && \ + name=$(shell json -f package.json name) && \ + publishedVer=$(shell npm view -j $(shell json -f package.json name)@$(shell json -f package.json version) version 2>/dev/null) && \ + if [[ -n "$$publishedVer" ]]; then \ + echo "error: $$name@$$ver is already published to npm"; \ + exit 1; \ + fi && \ + echo "** Are you sure you want to tag and publish $$name@$$ver to npm?" && \ + echo "** Enter to continue, Ctrl+C to abort." && \ + read + ver=$(shell cat package.json | json version) && \ + date=$(shell date -u "+%Y-%m-%d") && \ + git tag -a "$$ver" -m "version $$ver ($$date)" && \ + git push --tags origin && \ + npm publish + +.PHONY: docs +docs: toc + @[[ `which ronn` ]] || (echo "No 'ronn' on your PATH. Install with 'gem install ronn'" && exit 2) + mkdir -p man/man1 + ronn --style=toc --manual="bunyan manual" --date=$(shell git log -1 --pretty=format:%cd --date=short) --roff --html docs/bunyan.1.ronn + python -c 'import sys; h = open("docs/bunyan.1.html").read(); h = h.replace(".mp dt.flush {float:left;width:8ex}", ""); open("docs/bunyan.1.html", "w").write(h)' + python -c 'import sys; h = open("docs/bunyan.1.html").read(); h = h.replace("</body>", """<a href="https://github.com/trentm/node-bunyan"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a></body>"""); open("docs/bunyan.1.html", "w").write(h)' + @echo "# test with 'man ./docs/bunyan.1' and 'open ./docs/bunyan.1.html'" + +# Re-generate the README.md table of contents. +toc: + ./node_modules/.bin/markdown-toc -i README.md + + +.PHONY: publish +publish: + mkdir -p tmp + [[ -d tmp/bunyan-gh-pages ]] || git clone g...@github.com:trentm/node-bunyan.git tmp/bunyan-gh-pages + cd tmp/bunyan-gh-pages && git checkout gh-pages && git pull --rebase origin gh-pages + cp docs/index.html tmp/bunyan-gh-pages/index.html + cp docs/bunyan.1.html tmp/bunyan-gh-pages/bunyan.1.html + (cd tmp/bunyan-gh-pages \ + && git commit -a -m "publish latest docs" \ + && git push origin gh-pages || true) + +.PHONY: distclean +distclean: + rm -rf node_modules + + +#---- test + +.PHONY: test +test: $(NODEUNIT) + test -z "$(DTRACE_UP_IN_HERE)" || test -n "$(SKIP_DTRACE)" || \ + (node -e 'require("dtrace-provider").createDTraceProvider("isthisthingon")' && \ + echo "\nNote: Use 'SKIP_DTRACE=1 make test' to skip parts of the test suite that require root." && \ + $(SUDO) $(NODEUNIT) test/dtrace.test.js) + $(NODEUNIT) $(NON_DTRACE_TEST_FILES) + +# Test will all node supported versions (presumes install locations I use on +# my machine -- "~/opt/node-VER"): +# Note: 'test4' is last so (if all is well) I end up with a binary +# dtrace-provider build for my current default node version. +.PHONY: testall +testall: test7 test6 test012 test010 test4 + +.PHONY: test7 +test7: + @echo "# Test node 7.x (with node `$(NODEOPT)/node-7/bin/node --version`)" + @$(NODEOPT)/node-7/bin/node --version | grep '^v7\.' + PATH="$(NODEOPT)/node-7/bin:$(PATH)" make distclean all test +.PHONY: test6 +test6: + @echo "# Test node 6.x (with node `$(NODEOPT)/node-6/bin/node --version`)" + @$(NODEOPT)/node-6/bin/node --version | grep '^v6\.' + PATH="$(NODEOPT)/node-6/bin:$(PATH)" make distclean all test +.PHONY: test4 +test4: + @echo "# Test node 4.x (with node `$(NODEOPT)/node-4/bin/node --version`)" + @$(NODEOPT)/node-4/bin/node --version | grep '^v4\.' + PATH="$(NODEOPT)/node-4/bin:$(PATH)" make distclean all test +.PHONY: test012 +test012: + @echo "# Test node 0.12.x (with node `$(NODEOPT)/node-0.12/bin/node --version`)" + @$(NODEOPT)/node-0.12/bin/node --version | grep '^v0\.12\.' + PATH="$(NODEOPT)/node-0.12/bin:$(PATH)" make distclean all test +.PHONY: test010 +test010: + @echo "# Test node 0.10.x (with node `$(NODEOPT)/node-0.10/bin/node --version`)" + @$(NODEOPT)/node-0.10/bin/node --version | grep '^v0\.10\.' + PATH="$(NODEOPT)/node-0.10/bin:$(PATH)" make distclean all test + + +#---- check + +.PHONY: check-jsstyle +check-jsstyle: $(JSSTYLE_FILES) + ./tools/jsstyle -o indent=4,doxygen,unparenthesized-return=0,blank-after-start-comment=0,leading-right-paren-ok=1 $(JSSTYLE_FILES) + +.PHONY: check +check: check-jsstyle versioncheck + @echo "Check ok." + +.PHONY: prepush +prepush: check testall + @echo "Okay to push." http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/bunyan/README.md ---------------------------------------------------------------------- diff --git a/node_modules/bunyan/README.md b/node_modules/bunyan/README.md new file mode 100644 index 0000000..1e225ec --- /dev/null +++ b/node_modules/bunyan/README.md @@ -0,0 +1,1320 @@ +[![npm version](https://img.shields.io/npm/v/bunyan.svg?style=flat)](https://www.npmjs.com/package/bunyan) + +Bunyan is **a simple and fast JSON logging library** for node.js services: + +```js +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](https://raw.github.com/trentm/node-bunyan/master/tools/screenshot1.png) + +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 + +<!-- toc --> + +- [Current Status](#current-status) +- [Installation](#installation) +- [Features](#features) +- [Introduction](#introduction) + * [Constructor API](#constructor-api) + * [Log Method API](#log-method-api) + * [CLI Usage](#cli-usage) + * [Streams Introduction](#streams-introduction) + * [log.child](#logchild) + * [Serializers](#serializers) + + [Standard Serializers](#standard-serializers) + * [src](#src) +- [Levels](#levels) + * [Level suggestions](#level-suggestions) +- [Log Record Fields](#log-record-fields) + * [Core fields](#core-fields) + * [Recommended/Best Practice Fields](#recommendedbest-practice-fields) + * [Other fields to consider](#other-fields-to-consider) +- [Streams](#streams) + * [stream errors](#stream-errors) + * [stream type: `stream`](#stream-type-stream) + * [stream type: `file`](#stream-type-file) + * [stream type: `rotating-file`](#stream-type-rotating-file) + * [stream type: `raw`](#stream-type-raw) + * [`raw` + RingBuffer Stream](#raw--ringbuffer-stream) + * [third-party streams](#third-party-streams) +- [Runtime log snooping via DTrace](#runtime-log-snooping-via-dtrace) + * [DTrace examples](#dtrace-examples) +- [Runtime environments](#runtime-environments) + * [Browserify](#browserify) + * [Webpack](#webpack) +- [Versioning](#versioning) +- [License](#license) +- [See Also](#see-also) + +<!-- tocstop --> + +# 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 +<a href="https://twitter.com/intent/user?screen_name=trentmick" target="_blank">@trentmick</a> +for updates to Bunyan. + +There is an email discussion list +[bunyan-logg...@googlegroups.com](mailto:bunyan-logg...@googlegroups.com), +also [as a forum in the +browser](https://groups.google.com/forum/?fromgroups#!forum/bunyan-logging). + + +# Installation + +```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` +to get the bunyan CLI on your PATH, then use local bunyan installs for +node.js library usage of bunyan in your apps. + + +# Features + +- elegant [log method API](#log-method-api) +- extensible [streams](#streams) system for controlling where log records + go (to a stream, to a file, [log file rotation](#stream-type-rotating-file), + etc.) +- [`bunyan` CLI](#cli-usage) for pretty-printing and filtering of Bunyan logs +- simple include of log call source location (file, line, function) with + [`src: true`](#src) +- lightweight specialization of Logger instances with [`log.child`](#logchild) +- custom rendering of logged objects with ["serializers"](#serializers) +- [Runtime log snooping via DTrace support](#runtime-log-snooping-via-dtrace) +- Support for a few [runtime environments](#runtime-environments): Node.js, + [Browserify](http://browserify.org/), [Webpack](https://webpack.github.io/), [NW.js](http://nwjs.io/). + + +# Introduction + +Like most logging libraries you create a Logger instance and call methods +named after the logging levels: + +```js +// 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". + +```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} +``` + + +## Constructor API + +```js +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: + +```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({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](#core-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.: + +```js +log.info({widget: mywidget}, ...) +``` + +This will dove-tail with [Bunyan serializer support](#serializers), 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](#levels) 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: + +```sh +$ 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: + +```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): + +```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. + + +## Streams Introduction + +By default, log output is to stdout and at the "info" level. Explicitly that +looks like: + +```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**. + +```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 +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: + +```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.') +} + +log.info('start'); +var wuzzle = new Wuzzle({log: log}); +wuzzle.woos(); +log.info('done'); +``` + +Running that looks like (raw): + +```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): + +```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. +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: + +```js +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: + +```js +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: + +```js +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.: + +```js +var log = bunyan.createLogger({name: 'myapp'}); +log.addSerializers({req: reqSerializer}); +``` + + +**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 +in your log record will be replaced with a short error message. + + +### Standard Serializers + +Bunyan includes a small set of "standard serializers", exported as +`bunyan.stdSerializers`. Their use is completely optional. Example using +all of them: + +```js +var log = bunyan.createLogger({ + name: 'myapp', + serializers: bunyan.stdSerializers +}); +``` + +or particular ones: + +```js +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](https://github.com/davepacheco/node-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](https://github.com/restify/node-restify/blob/ac13902ad9716dcb20aaa62295403983075b1841/lib/plugins/audit.js#L38-L87) +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: + +```js +var log = bunyan.createLogger({src: true, ...}); +``` + +This adds the call source info with the 'src' field, like this: + +```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.** + + +# 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": + +```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 +``` + + +## 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: + +```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: + +```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 + +- `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 + vi `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](http://en.wikipedia.org/wiki/ISO_8601) format and in UTC, + as from + [`Date.toISOString()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/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). + + +## Recommended/Best Practice Fields + +- `err`: Object. A caught JS exception. Log that thing with `log.info(err)` + to get: + + ```js + ... + "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](https://github.com/mcavage/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: + + ```js + { + "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: + + ```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 + +- `req.username`: Authenticated user (or for a 401, the user attempting to + auth). +- Some mechanism to calculate response latency. "restify" users will have + a "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](https://nodejs.org/docs/latest/api/all.html#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: + +```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`). + +```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 +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. + + +## 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](#stream-type-file), so you can do this: + +```js +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](https://nodejs.org/api/events.html#events_error_events) for details. + + +## stream type: `stream` + +A `type === 'stream'` is a plain ol' node.js [Writable +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`. + +```js +var log = bunyan.createLogger({ + name: 'foo', + streams: [{ + stream: process.stderr + // `type: 'stream'` is implied + }] +}); +``` + +<table> +<tr> +<th>Field</th> +<th>Required?</th> +<th>Default</th> +<th>Description</th> +</tr> +<tr> +<td>stream</td> +<td>Yes</td> +<td>-</td> +<td>A "Writable Stream", e.g. a std handle or an open file write stream.</td> +</tr> +<tr> +<td>type</td> +<td>No</td> +<td>n/a</td> +<td>`type == 'stream'` is implied if the `stream` field is given.</td> +</tr> +<tr> +<td>level</td> +<td>No</td> +<td>info</td> +<td>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).</td> +</tr> +<tr> +<td>name</td> +<td>No</td> +<td>-</td> +<td>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.</td> +</tr> +</table> + + +## stream type: `file` + +A `type === 'file'` stream requires a "path" field. Bunyan will open this +file for appending. E.g.: + +```js +var log = bunyan.createLogger({ + name: 'foo', + streams: [{ + path: '/var/log/foo.log', + // `type: 'file'` is implied + }] +}); +``` + +<table> +<tr> +<th>Field</th> +<th>Required?</th> +<th>Default</th> +<th>Description</th> +</tr> +<tr> +<td>path</td> +<td>Yes</td> +<td>-</td> +<td>A file path to which to log.</td> +</tr> +<tr> +<td>type</td> +<td>No</td> +<td>n/a</td> +<td>`type == 'file'` is implied if the `path` field is given.</td> +</tr> +<tr> +<td>level</td> +<td>No</td> +<td>info</td> +<td>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).</td> +</tr> +<tr> +<td>name</td> +<td>No</td> +<td>-</td> +<td>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.</td> +</tr> +</table> + + +## 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](https://github.com/trentm/node-bunyan/pull/97)), 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](http://nodejs.org/docs/latest/api/all.html#all_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](https://github.com/trentm/node-bunyan/issues/117#issuecomment-44804938) +for details. + +A `type === 'rotating-file'` is a file stream that handles file automatic +rotation. + +```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: + +```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. + +<table> +<tr> +<th>Field</th> +<th>Required?</th> +<th>Default</th> +<th>Description</th> +</tr> +<tr> +<td>type</td> +<td>Yes</td> +<td>-</td> +<td>"rotating-file"</td> +</tr> +<tr> +<td>path</td> +<td>Yes</td> +<td>-</td> +<td>A file path to which to log. Rotated files will be "$path.0", +"$path.1", ...</td> +</tr> +<tr> +<td>period</td> +<td>No</td> +<td>1d</td> +<td>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).</td> +</tr> +<tr> +<td>count</td> +<td>No</td> +<td>10</td> +<td>The number of rotated files to keep.</td> +</tr> +<tr> +<td>level</td> +<td>No</td> +<td>info</td> +<td>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`, ...).</td> +</tr> +<tr> +<td>name</td> +<td>No</td> +<td>-</td> +<td>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.</td> +</tr> +</table> + + +**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 + +See the [user-maintained list in the Bunyan +wiki](https://github.com/trentm/node-bunyan/wiki/Awesome-Bunyan). + + +# 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 +``` + + +# Runtime environments + +Node-bunyan supports running in a few runtime environments: + +- [Node.js](https://nodejs.org/) +- [Browserify](http://browserify.org/): See the + [Browserify section](#browserify) below. +- [Webpack](https://webpack.github.io/): See the [Webpack section](#webpack) below. +- [NW.js](http://nwjs.io/) + +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](https://github.com/trentm/node-bunyan/issues/new) +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](https://github.com/trentm/node-bunyan/issues/342). + +## 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 +<script src="play.browser.js"></script> +``` + +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 + <!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: + + ```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) + +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: + +```js +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 +Webpack can work with the same example Browserify above. To do this, we need to make webpack ignore optional files: +Create "empty-shim.js": +```javascript +// This is an empty shim for things that should be not be included in webpack +``` +Now tell webpack to use this file for +[optional dependencies](https://webpack.github.io/docs/configuration.html#resolve-alias) +in your "webpack.config.js": +``` +resolve: { + // These shims are needed for bunyan + alias: { + 'dtrace-provider': '/path/to/shim/empty_shim.js', + fs: '/path/to/shim/empty_shim.js', + 'safe-json-stringify': '/path/to/shim/empty_shim.js', + mv: '/path/to/shim/empty_shim.js', + 'source-map-support': '/path/to/shim/empty_shim.js' + } +} +``` +Now webpack builds, ignoring these optional dependencies via shimming in an empty JS file! + +# 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](http://semver.org/). + +# License + +[MIT](./LICENSE.txt). + +# See Also + +See the [user-maintained list of Bunyan-related software in the Bunyan +wiki](https://github.com/trentm/node-bunyan/wiki/Awesome-Bunyan). http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/bunyan/TODO.md ---------------------------------------------------------------------- diff --git a/node_modules/bunyan/TODO.md b/node_modules/bunyan/TODO.md new file mode 100644 index 0000000..0f2f2c5 --- /dev/null +++ b/node_modules/bunyan/TODO.md @@ -0,0 +1,73 @@ +- `bunyan` (without redir) ^C should stop, doesn't since recent change +- man page for the bunyan CLI (refer to it in the readme) +- `tail -f`-like support +- 2.0 (?) with `v: 1` in log records. Fwd/bwd compat in `bunyan` CLI + +# docs + +- document log.addStream() and log.addSerializers() + + +# someday/maybe + +- full-on docs +- better examples/ +- better coloring +- look at pino (bunyan style, perf benefits) +- would be exciting to have bunyan support in http://lnav.org/ if that + made sense +- "template" support for 'rotating-file' stream to get dated rolled files +- "all" or "off" levels? log4j? logging.py? + logging.py has NOTSET === 0. I think that is only needed/used for + multi-level hierarchical effective level. +- buffered writes to increase speed: + - I'd start with a tools/timeoutput.js for some numbers to compare + before/after. Sustained high output to a file. + - perhaps this would be a "buffered: true" option on the stream object + - then wrap the "stream" with a local class that handles the buffering + - to finish this, need the 'log.close' and `process.on('exit', ...)` + work that Trent has started. +- "canWrite" handling for full streams. Need to buffer a la log4js +- test file log with logadm rotation: does it handle that? +- test suite: + - test for a cloned logger double-`stream.end()` causing problems. + Perhaps the "closeOnExit" for existing streams should be false for + clones. + - test that a `log.clone(...)` adding a new field matching a serializer + works *and* that an existing field in the parent is not *re-serialized*. +- split out `bunyan` cli to a "bunyan" or "bunyan-reader" or "node-bunyan-reader" + as the basis for tools to consume bunyan logs. It can grow indep of node-bunyan + for generating the logs. + It would take a Bunyan log record object and be expected to emit it. + + node-bunyan-reader + .createReadStream(path, [options]) ? + +- coloring bug: in less the indented extra info lines only have the first + line colored. Do we need the ANSI char on *each* line? That'll be + slower. +- document "well-known" keys from bunyan CLI p.o.v.. Add "client_req". +- More `bunyan` output formats and filtering features. +- Think about a bunyan dashboard that supports organizing and viewing logs + from multiple hosts and services. +- doc the restify RequestCaptureStream usage of RingBuffer. Great example. +- A vim plugin (a la http://vim.cybermirror.org/runtime/autoload/zip.vim ?) to + allow browsing (read-only) a bunyan log in rendered form. +- Some speed comparisons with others to get a feel for Bunyan's speed. +- what about promoting 'latency' field and making that easier? +- `log.close` to close streams and shutdown and `this.closed` + process.on('exit', log.close) + -> 'end' for the name +- bunyan cli: more layouts (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html) + Custom log formats (in config file? in '-f' arg) using printf or hogan.js + or whatever. Dap wants field width control for lining up. Hogan.js is + probably overkill for this. +- loggly example using raw streams, hook.io?, whatever. +- serializer support: + - restify-server.js example -> restifyReq ? or have `req` detect that. + That is nicer for the "use all standard ones". *Does* restify req + have anything special? + - differential HTTP *client* req/res with *server* req/res. +- statsd stream? http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/ + Think about it. +- web ui. Ideas: http://googlecloudplatform.blogspot.ca/2014/04/a-new-logs-viewer-for-google-cloud.html