Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 45KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  1. [![npm version](https://img.shields.io/npm/v/bunyan.svg?style=flat)](https://www.npmjs.com/package/bunyan)
  2. [![Build Status](https://travis-ci.org/trentm/node-bunyan.svg?branch=master)](https://travis-ci.org/trentm/node-bunyan)
  3. Bunyan is **a simple and fast JSON logging library** for node.js services:
  4. ```js
  5. var bunyan = require('bunyan');
  6. var log = bunyan.createLogger({name: "myapp"});
  7. log.info("hi");
  8. ```
  9. and **a `bunyan` CLI tool** for nicely viewing those logs:
  10. ![bunyan CLI screenshot](https://raw.github.com/trentm/node-bunyan/master/tools/screenshot1.png)
  11. Manifesto: Server logs should be structured. JSON's a good format. Let's do
  12. that. A log record is one line of `JSON.stringify`'d output. Let's also
  13. specify some common names for the requisite and common fields for a log
  14. record (see below).
  15. ## Table of Contents
  16. <!-- toc -->
  17. - [Current Status](#current-status)
  18. - [Installation](#installation)
  19. - [Features](#features)
  20. - [Introduction](#introduction)
  21. * [Constructor API](#constructor-api)
  22. * [Log Method API](#log-method-api)
  23. * [CLI Usage](#cli-usage)
  24. * [Streams Introduction](#streams-introduction)
  25. * [log.child](#logchild)
  26. * [Serializers](#serializers)
  27. + [Requirements for serializers functions](#requirements-for-serializers-functions)
  28. + [Standard Serializers](#standard-serializers)
  29. * [src](#src)
  30. - [Levels](#levels)
  31. * [Level suggestions](#level-suggestions)
  32. - [Log Record Fields](#log-record-fields)
  33. * [Core fields](#core-fields)
  34. * [Recommended/Best Practice Fields](#recommendedbest-practice-fields)
  35. * [Other fields to consider](#other-fields-to-consider)
  36. - [Streams](#streams)
  37. * [Adding a Stream](#adding-a-stream)
  38. * [stream errors](#stream-errors)
  39. * [stream type: `stream`](#stream-type-stream)
  40. * [stream type: `file`](#stream-type-file)
  41. * [stream type: `rotating-file`](#stream-type-rotating-file)
  42. * [stream type: `raw`](#stream-type-raw)
  43. * [`raw` + RingBuffer Stream](#raw--ringbuffer-stream)
  44. * [third-party streams](#third-party-streams)
  45. - [Runtime log snooping via DTrace](#runtime-log-snooping-via-dtrace)
  46. * [DTrace examples](#dtrace-examples)
  47. - [Runtime environments](#runtime-environments)
  48. * [Browserify](#browserify)
  49. * [Webpack](#webpack)
  50. - [Versioning](#versioning)
  51. - [License](#license)
  52. - [See Also](#see-also)
  53. <!-- tocstop -->
  54. # Current Status
  55. Solid core functionality is there. Joyent is using this for a number of
  56. production services. Bunyan supports node 0.10 and greater. Follow
  57. <a href="https://twitter.com/intent/user?screen_name=trentmick" target="_blank">@trentmick</a>
  58. for updates to Bunyan.
  59. There is an email discussion list
  60. [bunyan-logging@googlegroups.com](mailto:bunyan-logging@googlegroups.com),
  61. also [as a forum in the
  62. browser](https://groups.google.com/forum/?fromgroups#!forum/bunyan-logging).
  63. # Installation
  64. ```sh
  65. npm install bunyan
  66. ```
  67. **Tip**: The `bunyan` CLI tool is written to be compatible (within reason) with
  68. all versions of Bunyan logs. Therefore you might want to `npm install -g bunyan`
  69. to get the bunyan CLI on your PATH, then use local bunyan installs for
  70. node.js library usage of bunyan in your apps.
  71. # Features
  72. - elegant [log method API](#log-method-api)
  73. - extensible [streams](#streams) system for controlling where log records
  74. go (to a stream, to a file, [log file rotation](#stream-type-rotating-file),
  75. etc.)
  76. - [`bunyan` CLI](#cli-usage) for pretty-printing and filtering of Bunyan logs
  77. - simple include of log call source location (file, line, function) with
  78. [`src: true`](#src)
  79. - lightweight specialization of Logger instances with [`log.child`](#logchild)
  80. - custom rendering of logged objects with ["serializers"](#serializers)
  81. - [Runtime log snooping via DTrace support](#runtime-log-snooping-via-dtrace)
  82. - Support for a few [runtime environments](#runtime-environments): Node.js,
  83. [Browserify](http://browserify.org/), [Webpack](https://webpack.github.io/), [NW.js](http://nwjs.io/).
  84. # Introduction
  85. Like most logging libraries you create a Logger instance and call methods
  86. named after the logging levels:
  87. ```js
  88. // hi.js
  89. var bunyan = require('bunyan');
  90. var log = bunyan.createLogger({name: 'myapp'});
  91. log.info('hi');
  92. log.warn({lang: 'fr'}, 'au revoir');
  93. ```
  94. All loggers must provide a "name". This is somewhat akin to the log4j logger
  95. "name", but Bunyan doesn't do hierarchical logger names.
  96. **Bunyan log records are JSON.** A few fields are added automatically:
  97. "pid", "hostname", "time" and "v".
  98. ```sh
  99. $ node hi.js
  100. {"name":"myapp","hostname":"banana.local","pid":40161,"level":30,"msg":"hi","time":"2013-01-04T18:46:23.851Z","v":0}
  101. {"name":"myapp","hostname":"banana.local","pid":40161,"level":40,"lang":"fr","msg":"au revoir","time":"2013-01-04T18:46:23.853Z","v":0}
  102. ```
  103. ## Constructor API
  104. ```js
  105. var bunyan = require('bunyan');
  106. var log = bunyan.createLogger({
  107. name: <string>, // Required
  108. level: <level name or number>, // Optional, see "Levels" section
  109. stream: <node.js stream>, // Optional, see "Streams" section
  110. streams: [<bunyan streams>, ...], // Optional, see "Streams" section
  111. serializers: <serializers mapping>, // Optional, see "Serializers" section
  112. src: <boolean>, // Optional, see "src" section
  113. // Any other fields are added to all log records as is.
  114. foo: 'bar',
  115. ...
  116. });
  117. ```
  118. ## Log Method API
  119. The example above shows two different ways to call `log.info(...)`. The
  120. full API is:
  121. ```js
  122. log.info(); // Returns a boolean: is the "info" level enabled?
  123. // This is equivalent to `log.isInfoEnabled()` or
  124. // `log.isEnabledFor(INFO)` in log4j.
  125. log.info('hi'); // Log a simple string message (or number).
  126. log.info('hi %s', bob, anotherVar); // Uses `util.format` for msg formatting.
  127. log.info({foo: 'bar'}, 'hi');
  128. // The first field can optionally be a "fields" object, which
  129. // is merged into the log record.
  130. log.info(err); // Special case to log an `Error` instance to the record.
  131. // This adds an "err" field with exception details
  132. // (including the stack) and sets "msg" to the exception
  133. // message.
  134. log.info(err, 'more on this: %s', more);
  135. // ... or you can specify the "msg".
  136. log.info({foo: 'bar', err: err}, 'some msg about this error');
  137. // To pass in an Error *and* other fields, use the `err`
  138. // field name for the Error instance.
  139. ```
  140. Note that this implies **you cannot blindly pass any object as the first
  141. argument to log it** because that object might include fields that collide with
  142. Bunyan's [core record fields](#core-fields). In other words,
  143. `log.info(mywidget)` may not yield what you expect. Instead of a string
  144. representation of `mywidget` that other logging libraries may give you, Bunyan
  145. will try to JSON-ify your object. It is a Bunyan best practice to always give a
  146. field name to included objects, e.g.:
  147. ```js
  148. log.info({widget: mywidget}, ...)
  149. ```
  150. This will dove-tail with [Bunyan serializer support](#serializers), discussed
  151. later.
  152. The same goes for all of Bunyan's log levels: `log.trace`, `log.debug`,
  153. `log.info`, `log.warn`, `log.error`, and `log.fatal`. See the [levels
  154. section](#levels) below for details and suggestions.
  155. ## CLI Usage
  156. Bunyan log output is a stream of JSON objects. This is great for processing,
  157. but not for reading directly. A **`bunyan` tool** is provided **for
  158. pretty-printing bunyan logs** and for **filtering** (e.g.
  159. `| bunyan -c 'this.foo == "bar"'`). Using our example above:
  160. ```sh
  161. $ node hi.js | ./node_modules/.bin/bunyan
  162. [2013-01-04T19:01:18.241Z] INFO: myapp/40208 on banana.local: hi
  163. [2013-01-04T19:01:18.242Z] WARN: myapp/40208 on banana.local: au revoir (lang=fr)
  164. ```
  165. See the screenshot above for an example of the default coloring of rendered
  166. log output. That example also shows the nice formatting automatically done for
  167. some well-known log record fields (e.g. `req` is formatted like an HTTP request,
  168. `res` like an HTTP response, `err` like an error stack trace).
  169. One interesting feature is **filtering** of log content, which can be useful
  170. for digging through large log files or for analysis. We can filter only
  171. records above a certain level:
  172. ```sh
  173. $ node hi.js | bunyan -l warn
  174. [2013-01-04T19:08:37.182Z] WARN: myapp/40353 on banana.local: au revoir (lang=fr)
  175. ```
  176. Or filter on the JSON fields in the records (e.g. only showing the French
  177. records in our contrived example):
  178. ```sh
  179. $ node hi.js | bunyan -c 'this.lang == "fr"'
  180. [2013-01-04T19:08:26.411Z] WARN: myapp/40342 on banana.local: au revoir (lang=fr)
  181. ```
  182. See `bunyan --help` for other facilities.
  183. ## Streams Introduction
  184. By default, log output is to stdout and at the "info" level. Explicitly that
  185. looks like:
  186. ```js
  187. var log = bunyan.createLogger({
  188. name: 'myapp',
  189. stream: process.stdout,
  190. level: 'info'
  191. });
  192. ```
  193. That is an abbreviated form for a single stream. **You can define multiple
  194. streams at different levels**.
  195. ```js
  196. var log = bunyan.createLogger({
  197. name: 'myapp',
  198. streams: [
  199. {
  200. level: 'info',
  201. stream: process.stdout // log INFO and above to stdout
  202. },
  203. {
  204. level: 'error',
  205. path: '/var/tmp/myapp-error.log' // log ERROR and above to a file
  206. }
  207. ]
  208. });
  209. ```
  210. More on streams in the [Streams section](#streams) below.
  211. ## log.child
  212. Bunyan has a concept of a child logger to **specialize a logger for a
  213. sub-component of your application**, i.e. to create a new logger with
  214. additional bound fields that will be included in its log records. A child
  215. logger is created with `log.child(...)`.
  216. In the following example, logging on a "Wuzzle" instance's `this.log` will
  217. be exactly as on the parent logger with the addition of the `widget_type`
  218. field:
  219. ```js
  220. var bunyan = require('bunyan');
  221. var log = bunyan.createLogger({name: 'myapp'});
  222. function Wuzzle(options) {
  223. this.log = options.log.child({widget_type: 'wuzzle'});
  224. this.log.info('creating a wuzzle')
  225. }
  226. Wuzzle.prototype.woos = function () {
  227. this.log.warn('This wuzzle is woosey.')
  228. }
  229. log.info('start');
  230. var wuzzle = new Wuzzle({log: log});
  231. wuzzle.woos();
  232. log.info('done');
  233. ```
  234. Running that looks like (raw):
  235. ```sh
  236. $ node myapp.js
  237. {"name":"myapp","hostname":"myhost","pid":34572,"level":30,"msg":"start","time":"2013-01-04T07:47:25.814Z","v":0}
  238. {"name":"myapp","hostname":"myhost","pid":34572,"widget_type":"wuzzle","level":30,"msg":"creating a wuzzle","time":"2013-01-04T07:47:25.815Z","v":0}
  239. {"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}
  240. {"name":"myapp","hostname":"myhost","pid":34572,"level":30,"msg":"done","time":"2013-01-04T07:47:25.816Z","v":0}
  241. ```
  242. And with the `bunyan` CLI (using the "short" output mode):
  243. ```sh
  244. $ node myapp.js | bunyan -o short
  245. 07:46:42.707Z INFO myapp: start
  246. 07:46:42.709Z INFO myapp: creating a wuzzle (widget_type=wuzzle)
  247. 07:46:42.709Z WARN myapp: This wuzzle is woosey. (widget_type=wuzzle)
  248. 07:46:42.709Z INFO myapp: done
  249. ```
  250. A more practical example is in the
  251. [node-restify](https://github.com/mcavage/node-restify) web framework.
  252. Restify uses Bunyan for its logging. One feature of its integration, is that
  253. if `server.use(restify.requestLogger())` is used, each restify request handler
  254. includes a `req.log` logger that is:
  255. ```js
  256. log.child({req_id: <unique request id>}, true)
  257. ```
  258. Apps using restify can then use `req.log` and have all such log records
  259. include the unique request id (as "req\_id"). Handy.
  260. ## Serializers
  261. Bunyan has a concept of **"serializer" functions to produce a JSON-able object
  262. from a JavaScript object**, so you can easily do the following:
  263. ```js
  264. log.info({req: <request object>}, 'something about handling this request');
  265. ```
  266. and have the `req` entry in the log record be just a reasonable subset of
  267. `<request object>` fields (or computed data about those fields).
  268. A logger instance can have a `serializers` mapping of log record field name
  269. ("req" in this example) to a serializer function. When creating the log
  270. record, Bunyan will call the serializer function for fields of that name.
  271. An example:
  272. ```js
  273. function reqSerializer(req) {
  274. return {
  275. method: req.method,
  276. url: req.url,
  277. headers: req.headers
  278. };
  279. }
  280. var log = bunyan.createLogger({
  281. name: 'myapp',
  282. serializers: {
  283. req: reqSerializer
  284. }
  285. });
  286. ```
  287. Typically serializers are added to a logger at creation time via
  288. `bunyan.createLogger({..., serializers: <serializers>})`. However, serializers
  289. can be added after creation via `<logger>.addSerializers(...)`, e.g.:
  290. ```js
  291. var log = bunyan.createLogger({name: 'myapp'});
  292. log.addSerializers({req: reqSerializer});
  293. ```
  294. ### Requirements for serializers functions
  295. A serializer function is passed unprotected objects that are passed to the
  296. `log.info`, `log.debug`, etc. call. This means a poorly written serializer
  297. function can case side-effects. Logging shouldn't do that. Here are a few
  298. rules and best practices for serializer functions:
  299. - A serializer function *should never throw*. The bunyan library *does*
  300. protect somewhat from this: if the serializer throws an error, then
  301. bunyan will (a) write an ugly message on stderr (along with the traceback),
  302. and (b) the field in the log record will be replace with a short error message.
  303. For example:
  304. ```
  305. bunyan: ERROR: Exception thrown from the "foo" Bunyan serializer. This should never happen. This is a bug in that serializer function.
  306. TypeError: Cannot read property 'not' of undefined
  307. at Object.fooSerializer [as foo] (/Users/trentm/tm/node-bunyan/bar.js:8:26)
  308. at /Users/trentm/tm/node-bunyan/lib/bunyan.js:873:50
  309. at Array.forEach (native)
  310. at Logger._applySerializers (/Users/trentm/tm/node-bunyan/lib/bunyan.js:865:35)
  311. at mkRecord (/Users/trentm/tm/node-bunyan/lib/bunyan.js:978:17)
  312. at Logger.info (/Users/trentm/tm/node-bunyan/lib/bunyan.js:1044:19)
  313. at Object.<anonymous> (/Users/trentm/tm/node-bunyan/bar.js:13:5)
  314. at Module._compile (module.js:409:26)
  315. at Object.Module._extensions..js (module.js:416:10)
  316. at Module.load (module.js:343:32)
  317. {"name":"bar","hostname":"danger0.local","pid":47411,"level":30,"foo":"(Error in Bunyan log \"foo\" serializer broke field. See stderr for details.)","msg":"one","time":"2017-03-08T02:53:51.173Z","v":0}
  318. ```
  319. - A serializer function *should never mutate the given object*. Doing so will
  320. change the object in your application.
  321. - A serializer function *should be defensive*. In my experience it is common to
  322. set a serializer in an app, say for field name "foo", and then accidentally
  323. have a log line that passes a "foo" that is undefined, or null, or of some
  324. unexpected type. A good start at defensiveness is to start with this:
  325. ```javascript
  326. function fooSerializers(foo) {
  327. // Guard against foo be null/undefined. Check that expected fields
  328. // are defined.
  329. if (!foo || !foo.bar)
  330. return foo;
  331. var obj = {
  332. // Create the object to be logged.
  333. bar: foo.bar
  334. }
  335. return obj;
  336. };
  337. ```
  338. ### Standard Serializers
  339. Bunyan includes a small set of "standard serializers", exported as
  340. `bunyan.stdSerializers`. Their use is completely optional. Example using
  341. all of them:
  342. ```js
  343. var log = bunyan.createLogger({
  344. name: 'myapp',
  345. serializers: bunyan.stdSerializers
  346. });
  347. ```
  348. or particular ones:
  349. ```js
  350. var log = bunyan.createLogger({
  351. name: 'myapp',
  352. serializers: {err: bunyan.stdSerializers.err}
  353. });
  354. ```
  355. Standard serializers are:
  356. | Field | Description |
  357. | ----- | ----------- |
  358. | 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). |
  359. | req | Common fields from a node.js HTTP request object. |
  360. | res | Common fields from a node.js HTTP response object. |
  361. Note that the `req` and `res` serializers intentionally do not include the
  362. request/response *body*, as that can be prohibitively large. If helpful, the
  363. [restify framework's audit logger plugin](https://github.com/restify/node-restify/blob/ac13902ad9716dcb20aaa62295403983075b1841/lib/plugins/audit.js#L38-L87)
  364. has its own req/res serializers that include more information (optionally
  365. including the body).
  366. ## src
  367. The **source file, line and function of the log call site** can be added to
  368. log records by using the `src: true` config option:
  369. ```js
  370. var log = bunyan.createLogger({src: true, ...});
  371. ```
  372. This adds the call source info with the 'src' field, like this:
  373. ```js
  374. {
  375. "name": "src-example",
  376. "hostname": "banana.local",
  377. "pid": 123,
  378. "component": "wuzzle",
  379. "level": 4,
  380. "msg": "This wuzzle is woosey.",
  381. "time": "2012-02-06T04:19:35.605Z",
  382. "src": {
  383. "file": "/Users/trentm/tm/node-bunyan/examples/src.js",
  384. "line": 20,
  385. "func": "Wuzzle.woos"
  386. },
  387. "v": 0
  388. }
  389. ```
  390. **WARNING: Determining the call source info is slow. Never use this option
  391. in production.**
  392. # Levels
  393. The log levels in bunyan are as follows. The level descriptions are best
  394. practice *opinions* of the author.
  395. - "fatal" (60): The service/app is going to stop or become unusable now.
  396. An operator should definitely look into this soon.
  397. - "error" (50): Fatal for a particular request, but the service/app continues
  398. servicing other requests. An operator should look at this soon(ish).
  399. - "warn" (40): A note on something that should probably be looked at by an
  400. operator eventually.
  401. - "info" (30): Detail on regular operation.
  402. - "debug" (20): Anything else, i.e. too verbose to be included in "info" level.
  403. - "trace" (10): Logging from external libraries used by your app or *very*
  404. detailed application logging.
  405. Setting a logger instance (or one of its streams) to a particular level implies
  406. that all log records *at that level and above* are logged. E.g. a logger set to
  407. level "info" will log records at level info and above (warn, error, fatal).
  408. While using log level *names* is preferred, the actual level values are integers
  409. internally (10 for "trace", ..., 60 for "fatal"). Constants are defined for
  410. the levels: `bunyan.TRACE` ... `bunyan.FATAL`. The lowercase level names are
  411. aliases supported in the API, e.g. `log.level("info")`. There is one exception:
  412. DTrace integration uses the level names. The fired DTrace probes are named
  413. 'bunyan-$levelName'.
  414. Here is the API for querying and changing levels on an existing logger.
  415. Recall that a logger instance has an array of output "streams":
  416. ```js
  417. log.level() -> INFO // gets current level (lowest level of all streams)
  418. log.level(INFO) // set all streams to level INFO
  419. log.level("info") // set all streams to level INFO
  420. log.levels() -> [DEBUG, INFO] // get array of levels of all streams
  421. log.levels(0) -> DEBUG // get level of stream at index 0
  422. log.levels("foo") // get level of stream with name "foo"
  423. log.levels(0, INFO) // set level of stream 0 to INFO
  424. log.levels(0, "info") // can use "info" et al aliases
  425. log.levels("foo", WARN) // set stream named "foo" to WARN
  426. ```
  427. ## Level suggestions
  428. Trent's biased suggestions for server apps: Use "debug" sparingly. Information
  429. that will be useful to debug errors *post mortem* should usually be included in
  430. "info" messages if it's generally relevant or else with the corresponding
  431. "error" event. Don't rely on spewing mostly irrelevant debug messages all the
  432. time and sifting through them when an error occurs.
  433. Trent's biased suggestions for node.js libraries: IMHO, libraries should only
  434. ever log at `trace`-level. Fine control over log output should be up to the
  435. app using a library. Having a library that spews log output at higher levels
  436. gets in the way of a clear story in the *app* logs.
  437. # Log Record Fields
  438. This section will describe *rules* for the Bunyan log format: field names,
  439. field meanings, required fields, etc. However, a Bunyan library doesn't
  440. strictly enforce all these rules while records are being emitted. For example,
  441. Bunyan will add a `time` field with the correct format to your log records,
  442. but you can specify your own. It is the caller's responsibility to specify
  443. the appropriate format.
  444. The reason for the above leniency is because IMO logging a message should
  445. never break your app. This leads to this rule of logging: **a thrown
  446. exception from `log.info(...)` or equivalent (other than for calling with the
  447. incorrect signature) is always a bug in Bunyan.**
  448. A typical Bunyan log record looks like this:
  449. ```js
  450. {"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}
  451. ```
  452. Pretty-printed:
  453. ```js
  454. {
  455. "name": "myserver",
  456. "hostname": "banana.local",
  457. "pid": 123,
  458. "req": {
  459. "method": "GET",
  460. "url": "/path?q=1#anchor",
  461. "headers": {
  462. "x-hi": "Mom",
  463. "connection": "close"
  464. },
  465. "remoteAddress": "120.0.0.1",
  466. "remotePort": 51244
  467. },
  468. "level": 3,
  469. "msg": "start request",
  470. "time": "2012-02-03T19:02:57.534Z",
  471. "v": 0
  472. }
  473. ```
  474. ## Core fields
  475. - `v`: Required. Integer. Added by Bunyan. Cannot be overridden.
  476. This is the Bunyan log format version (`require('bunyan').LOG_VERSION`).
  477. The log version is a single integer. `0` is until I release a version
  478. "1.0.0" of node-bunyan. Thereafter, starting with `1`, this will be
  479. incremented if there is any backward incompatible change to the log record
  480. format. Details will be in "CHANGES.md" (the change log).
  481. - `level`: Required. Integer. Added by Bunyan. Cannot be overridden.
  482. See the "Levels" section.
  483. - `name`: Required. String. Provided at Logger creation.
  484. You must specify a name for your logger when creating it. Typically this
  485. is the name of the service/app using Bunyan for logging.
  486. - `hostname`: Required. String. Provided or determined at Logger creation.
  487. You can specify your hostname at Logger creation or it will be retrieved
  488. vi `os.hostname()`.
  489. - `pid`: Required. Integer. Filled in automatically at Logger creation.
  490. - `time`: Required. String. Added by Bunyan. Can be overridden.
  491. The date and time of the event in [ISO 8601
  492. Extended Format](http://en.wikipedia.org/wiki/ISO_8601) format and in UTC,
  493. as from
  494. [`Date.toISOString()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toISOString).
  495. - `msg`: Required. String.
  496. Every `log.debug(...)` et al call must provide a log message.
  497. - `src`: Optional. Object giving log call source info. This is added
  498. automatically by Bunyan if the "src: true" config option is given to the
  499. Logger. Never use in production as this is really slow.
  500. Go ahead and add more fields, and nested ones are fine (and recommended) as
  501. well. This is why we're using JSON. Some suggestions and best practices
  502. follow (feedback from actual users welcome).
  503. ## Recommended/Best Practice Fields
  504. - `err`: Object. A caught JS exception. Log that thing with `log.info(err)`
  505. to get:
  506. ```js
  507. ...
  508. "err": {
  509. "message": "boom",
  510. "name": "TypeError",
  511. "stack": "TypeError: boom\n at Object.<anonymous> ..."
  512. },
  513. "msg": "boom",
  514. ...
  515. ```
  516. Or use the `bunyan.stdSerializers.err` serializer in your Logger and
  517. do this `log.error({err: err}, "oops")`. See "examples/err.js".
  518. - `req_id`: String. A request identifier. Including this field in all logging
  519. tied to handling a particular request to your server is strongly suggested.
  520. This allows post analysis of logs to easily collate all related logging
  521. for a request. This really shines when you have a SOA with multiple services
  522. and you carry a single request ID from the top API down through all APIs
  523. (as [node-restify](https://github.com/mcavage/node-restify) facilitates
  524. with its 'Request-Id' header).
  525. - `req`: An HTTP server request. Bunyan provides `bunyan.stdSerializers.req`
  526. to serialize a request with a suggested set of keys. Example:
  527. ```js
  528. {
  529. "method": "GET",
  530. "url": "/path?q=1#anchor",
  531. "headers": {
  532. "x-hi": "Mom",
  533. "connection": "close"
  534. },
  535. "remoteAddress": "120.0.0.1",
  536. "remotePort": 51244
  537. }
  538. ```
  539. - `res`: An HTTP server response. Bunyan provides `bunyan.stdSerializers.res`
  540. to serialize a response with a suggested set of keys. Example:
  541. ```js
  542. {
  543. "statusCode": 200,
  544. "header": "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n"
  545. }
  546. ```
  547. ## Other fields to consider
  548. - `req.username`: Authenticated user (or for a 401, the user attempting to
  549. auth).
  550. - Some mechanism to calculate response latency. "restify" users will have
  551. a "X-Response-Time" header. A `latency` custom field would be fine.
  552. - `req.body`: If you know that request bodies are small (common in APIs,
  553. for example), then logging the request body is good.
  554. # Streams
  555. A "stream" is Bunyan's name for where it outputs log messages (the equivalent
  556. to a log4j Appender). Ultimately Bunyan uses a
  557. [Writable Stream](https://nodejs.org/docs/latest/api/all.html#writable_Stream)
  558. interface, but there are some additional attributes used to create and
  559. manage the stream. A Bunyan Logger instance has one or more streams.
  560. In general streams are specified with the "streams" option:
  561. ```js
  562. var bunyan = require('bunyan');
  563. var log = bunyan.createLogger({
  564. name: "foo",
  565. streams: [
  566. {
  567. stream: process.stderr,
  568. level: "debug"
  569. },
  570. ...
  571. ]
  572. });
  573. ```
  574. For convenience, if there is only one stream, it can specified with the
  575. "stream" and "level" options (internally converted to a `Logger.streams`).
  576. ```js
  577. var log = bunyan.createLogger({
  578. name: "foo",
  579. stream: process.stderr,
  580. level: "debug"
  581. });
  582. ```
  583. Note that "file" streams do not support this shortcut (partly for historical
  584. reasons and partly to not make it difficult to add a literal "path" field
  585. on log records).
  586. If neither "streams" nor "stream" are specified, the default is a stream of
  587. type "stream" emitting to `process.stdout` at the "info" level.
  588. ## Adding a Stream
  589. After a bunyan instance has been initialized, you may add additional streams by
  590. calling the `addStream` function.
  591. ```js
  592. var bunyan = require('bunyan');
  593. var log = bunyan.createLogger('myLogger');
  594. log.addStream({
  595. name: "myNewStream",
  596. stream: process.stderr,
  597. level: "debug"
  598. });
  599. ```
  600. ## stream errors
  601. A Bunyan logger instance can be made to re-emit "error" events from its
  602. streams. Bunyan does so by default for [`type === "file"`
  603. streams](#stream-type-file), so you can do this:
  604. ```js
  605. var log = bunyan.createLogger({name: 'mylog', streams: [{path: LOG_PATH}]});
  606. log.on('error', function (err, stream) {
  607. // Handle stream write or create error here.
  608. });
  609. ```
  610. As of bunyan@1.7.0, the `reemitErrorEvents` field can be used when adding a
  611. stream to control whether "error" events are re-emitted on the Logger. For
  612. example:
  613. var EventEmitter = require('events').EventEmitter;
  614. var util = require('util');
  615. function MyFlakyStream() {}
  616. util.inherits(MyFlakyStream, EventEmitter);
  617. MyFlakyStream.prototype.write = function (rec) {
  618. this.emit('error', new Error('boom'));
  619. }
  620. var log = bunyan.createLogger({
  621. name: 'this-is-flaky',
  622. streams: [
  623. {
  624. type: 'raw',
  625. stream: new MyFlakyStream(),
  626. reemitErrorEvents: true
  627. }
  628. ]
  629. });
  630. log.info('hi there');
  631. The behaviour is as follows:
  632. - `reemitErrorEvents` not specified: `file` streams will re-emit error events
  633. on the Logger instance.
  634. - `reemitErrorEvents: true`: error events will be re-emitted on the Logger
  635. for any stream with a `.on()` function -- which includes file streams,
  636. process.stdout/stderr, and any object that inherits from EventEmitter.
  637. - `reemitErrorEvents: false`: error events will not be re-emitted for any
  638. streams.
  639. Note: "error" events are **not** related to log records at the "error" level
  640. as produced by `log.error(...)`. See [the node.js docs on error
  641. events](https://nodejs.org/api/events.html#events_error_events) for details.
  642. ## stream type: `stream`
  643. A `type === 'stream'` is a plain ol' node.js [Writable
  644. Stream](http://nodejs.org/docs/latest/api/all.html#writable_Stream). A
  645. "stream" (the writable stream) field is required. E.g.: `process.stdout`,
  646. `process.stderr`.
  647. ```js
  648. var log = bunyan.createLogger({
  649. name: 'foo',
  650. streams: [{
  651. stream: process.stderr
  652. // `type: 'stream'` is implied
  653. }]
  654. });
  655. ```
  656. <table>
  657. <tr>
  658. <th>Field</th>
  659. <th>Required?</th>
  660. <th>Default</th>
  661. <th>Description</th>
  662. </tr>
  663. <tr>
  664. <td>stream</td>
  665. <td>Yes</td>
  666. <td>-</td>
  667. <td>A "Writable Stream", e.g. a std handle or an open file write stream.</td>
  668. </tr>
  669. <tr>
  670. <td>type</td>
  671. <td>No</td>
  672. <td>n/a</td>
  673. <td>`type == 'stream'` is implied if the `stream` field is given.</td>
  674. </tr>
  675. <tr>
  676. <td>level</td>
  677. <td>No</td>
  678. <td>info</td>
  679. <td>The level to which logging to this stream is enabled. If not
  680. specified it defaults to "info". If specified this can be one of the
  681. level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`,
  682. `bunyan.DEBUG`, ...). This serves as a severity threshold for that stream
  683. so logs of greater severity will also pass through (i.e. If level="warn",
  684. error and fatal will also pass through this stream).</td>
  685. </tr>
  686. <tr>
  687. <td>name</td>
  688. <td>No</td>
  689. <td>-</td>
  690. <td>A name for this stream. This may be useful for usage of `log.level(NAME,
  691. LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't
  692. used for anything else.</td>
  693. </tr>
  694. </table>
  695. ## stream type: `file`
  696. A `type === 'file'` stream requires a "path" field. Bunyan will open this
  697. file for appending. E.g.:
  698. ```js
  699. var log = bunyan.createLogger({
  700. name: 'foo',
  701. streams: [{
  702. path: '/var/log/foo.log',
  703. // `type: 'file'` is implied
  704. }]
  705. });
  706. ```
  707. <table>
  708. <tr>
  709. <th>Field</th>
  710. <th>Required?</th>
  711. <th>Default</th>
  712. <th>Description</th>
  713. </tr>
  714. <tr>
  715. <td>path</td>
  716. <td>Yes</td>
  717. <td>-</td>
  718. <td>A file path to which to log.</td>
  719. </tr>
  720. <tr>
  721. <td>type</td>
  722. <td>No</td>
  723. <td>n/a</td>
  724. <td>`type == 'file'` is implied if the `path` field is given.</td>
  725. </tr>
  726. <tr>
  727. <td>level</td>
  728. <td>No</td>
  729. <td>info</td>
  730. <td>The level to which logging to this stream is enabled. If not
  731. specified it defaults to "info". If specified this can be one of the
  732. level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`,
  733. `bunyan.DEBUG`, ...). This serves as a severity threshold for that
  734. stream so logs of greater severity will also pass through (i.e. If
  735. level="warn", error and fatal will also pass through this stream).</td>
  736. </tr>
  737. <tr>
  738. <td>name</td>
  739. <td>No</td>
  740. <td>-</td>
  741. <td>A name for this stream. This may be useful for usage of `log.level(NAME,
  742. LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't
  743. used for anything else.</td>
  744. </tr>
  745. </table>
  746. ## stream type: `rotating-file`
  747. **WARNING on node 0.8 usage:** Users of Bunyan's `rotating-file` should (a) be
  748. using at least bunyan 0.23.1 (with the fix for [this
  749. issue](https://github.com/trentm/node-bunyan/pull/97)), and (b) should use at
  750. least node 0.10 (node 0.8 does not support the `unref()` method on
  751. `setTimeout(...)` needed for the mentioned fix). The symptom is that process
  752. termination will hang for up to a full rotation period.
  753. **WARNING on [cluster](http://nodejs.org/docs/latest/api/all.html#all_cluster)
  754. usage:** Using Bunyan's `rotating-file` stream with node.js's "cluster" module
  755. can result in unexpected file rotation. You must not have multiple processes
  756. in the cluster logging to the same file path. In other words, you must have
  757. a separate log file path for the master and each worker in the cluster.
  758. Alternatively, consider using a system file rotation facility such as
  759. `logrotate` on Linux or `logadm` on SmartOS/Illumos. See
  760. [this comment on issue #117](https://github.com/trentm/node-bunyan/issues/117#issuecomment-44804938)
  761. for details.
  762. A `type === 'rotating-file'` is a file stream that handles file automatic
  763. rotation.
  764. ```js
  765. var log = bunyan.createLogger({
  766. name: 'foo',
  767. streams: [{
  768. type: 'rotating-file',
  769. path: '/var/log/foo.log',
  770. period: '1d', // daily rotation
  771. count: 3 // keep 3 back copies
  772. }]
  773. });
  774. ```
  775. This will rotate '/var/log/foo.log' every day (at midnight) to:
  776. ```sh
  777. /var/log/foo.log.0 # yesterday
  778. /var/log/foo.log.1 # 1 day ago
  779. /var/log/foo.log.2 # 2 days ago
  780. ```
  781. *Currently*, there is no support for providing a template for the rotated
  782. files, or for rotating when the log reaches a threshold size.
  783. <table>
  784. <tr>
  785. <th>Field</th>
  786. <th>Required?</th>
  787. <th>Default</th>
  788. <th>Description</th>
  789. </tr>
  790. <tr>
  791. <td>type</td>
  792. <td>Yes</td>
  793. <td>-</td>
  794. <td>"rotating-file"</td>
  795. </tr>
  796. <tr>
  797. <td>path</td>
  798. <td>Yes</td>
  799. <td>-</td>
  800. <td>A file path to which to log. Rotated files will be "$path.0",
  801. "$path.1", ...</td>
  802. </tr>
  803. <tr>
  804. <td>period</td>
  805. <td>No</td>
  806. <td>1d</td>
  807. <td>The period at which to rotate. This is a string of the format
  808. "$number$scope" where "$scope" is one of "ms" (milliseconds -- only useful for
  809. testing), "h" (hours), "d" (days), "w" (weeks), "m" (months), "y" (years). Or
  810. one of the following names can be used "hourly" (means 1h), "daily" (1d),
  811. "weekly" (1w), "monthly" (1m), "yearly" (1y). Rotation is done at the start of
  812. the scope: top of the hour (h), midnight (d), start of Sunday (w), start of the
  813. 1st of the month (m), start of Jan 1st (y).</td>
  814. </tr>
  815. <tr>
  816. <td>count</td>
  817. <td>No</td>
  818. <td>10</td>
  819. <td>The number of rotated files to keep.</td>
  820. </tr>
  821. <tr>
  822. <td>level</td>
  823. <td>No</td>
  824. <td>info</td>
  825. <td>The level at which logging to this stream is enabled. If not
  826. specified it defaults to "info". If specified this can be one of the
  827. level strings ("trace", "debug", ...) or constants (`bunyan.TRACE`,
  828. `bunyan.DEBUG`, ...).</td>
  829. </tr>
  830. <tr>
  831. <td>name</td>
  832. <td>No</td>
  833. <td>-</td>
  834. <td>A name for this stream. This may be useful for usage of `log.level(NAME,
  835. LEVEL)`. See the [Levels section](#levels) for details. A stream "name" isn't
  836. used for anything else.</td>
  837. </tr>
  838. </table>
  839. **Note on log rotation**: Often you may be using external log rotation utilities
  840. like `logrotate` on Linux or `logadm` on SmartOS/Illumos. In those cases, unless
  841. your are ensuring "copy and truncate" semantics (via `copytruncate` with
  842. logrotate or `-c` with logadm) then the fd for your 'file' stream will change.
  843. You can tell bunyan to reopen the file stream with code like this in your
  844. app:
  845. ```js
  846. var log = bunyan.createLogger(...);
  847. ...
  848. process.on('SIGUSR2', function () {
  849. log.reopenFileStreams();
  850. });
  851. ```
  852. where you'd configure your log rotation to send SIGUSR2 (or some other signal)
  853. to your process. Any other mechanism to signal your app to run
  854. `log.reopenFileStreams()` would work as well.
  855. ## stream type: `raw`
  856. - `raw`: Similar to a "stream" writable stream, except that the write method
  857. is given raw log record *Object*s instead of a JSON-stringified string.
  858. This can be useful for hooking on further processing to all Bunyan logging:
  859. pushing to an external service, a RingBuffer (see below), etc.
  860. ## `raw` + RingBuffer Stream
  861. Bunyan comes with a special stream called a RingBuffer which keeps the last N
  862. records in memory and does *not* write the data anywhere else. One common
  863. strategy is to log 'info' and higher to a normal log file but log all records
  864. (including 'trace') to a ringbuffer that you can access via a debugger, or your
  865. own HTTP interface, or a post-mortem facility like MDB or node-panic.
  866. To use a RingBuffer:
  867. ```js
  868. /* Create a ring buffer that stores the last 100 records. */
  869. var bunyan = require('bunyan');
  870. var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
  871. var log = bunyan.createLogger({
  872. name: 'foo',
  873. streams: [
  874. {
  875. level: 'info',
  876. stream: process.stdout
  877. },
  878. {
  879. level: 'trace',
  880. type: 'raw', // use 'raw' to get raw log record objects
  881. stream: ringbuffer
  882. }
  883. ]
  884. });
  885. log.info('hello world');
  886. console.log(ringbuffer.records);
  887. ```
  888. This example emits:
  889. ```js
  890. [ { name: 'foo',
  891. hostname: '912d2b29',
  892. pid: 50346,
  893. level: 30,
  894. msg: 'hello world',
  895. time: '2012-06-19T21:34:19.906Z',
  896. v: 0 } ]
  897. ```
  898. ## third-party streams
  899. See the [user-maintained list in the Bunyan
  900. wiki](https://github.com/trentm/node-bunyan/wiki/Awesome-Bunyan).
  901. # Runtime log snooping via DTrace
  902. On systems that support DTrace (e.g., illumos derivatives like SmartOS and
  903. OmniOS, FreeBSD, Mac), Bunyan will create a DTrace provider (`bunyan`) that
  904. makes available the following probes:
  905. ```sh
  906. log-trace
  907. log-debug
  908. log-info
  909. log-warn
  910. log-error
  911. log-fatal
  912. ```
  913. Each of these probes has a single argument: the string that would be
  914. written to the log. Note that when a probe is enabled, it will
  915. fire whenever the corresponding function is called, even if the level of
  916. the log message is less than that of any stream.
  917. ## DTrace examples
  918. Trace all log messages coming from any Bunyan module on the system.
  919. (The `-x strsize=4k` is to raise dtrace's default 256 byte buffer size
  920. because log messages are longer than typical dtrace probes.)
  921. ```sh
  922. dtrace -x strsize=4k -qn 'bunyan*:::log-*{printf("%d: %s: %s", pid, probefunc, copyinstr(arg0))}'
  923. ```
  924. Trace all log messages coming from the "wuzzle" component:
  925. ```sh
  926. dtrace -x strsize=4k -qn 'bunyan*:::log-*/strstr(this->str = copyinstr(arg0), "\"component\":\"wuzzle\"") != NULL/{printf("%s", this->str)}'
  927. ```
  928. Aggregate debug messages from process 1234, by message:
  929. ```sh
  930. dtrace -x strsize=4k -n 'bunyan1234:::log-debug{@[copyinstr(arg0)] = count()}'
  931. ```
  932. Have the bunyan CLI pretty-print the traced logs:
  933. ```sh
  934. dtrace -x strsize=4k -qn 'bunyan1234:::log-*{printf("%s", copyinstr(arg0))}' | bunyan
  935. ```
  936. A convenience handle has been made for this:
  937. ```sh
  938. bunyan -p 1234
  939. ```
  940. On systems that support the
  941. [`jstack`](http://dtrace.org/blogs/dap/2012/04/25/profiling-node-js/) action
  942. via a node.js helper, get a stack backtrace for any debug message that
  943. includes the string "danger!":
  944. ```sh
  945. dtrace -x strsize=4k -qn 'log-debug/strstr(copyinstr(arg0), "danger!") != NULL/{printf("\n%s", copyinstr(arg0)); jstack()}'
  946. ```
  947. Output of the above might be:
  948. ```
  949. {"name":"foo","hostname":"763bf293-d65c-42d5-872b-4abe25d5c4c7.local","pid":12747,"level":20,"msg":"danger!","time":"2012-10-30T18:28:57.115Z","v":0}
  950. node`0x87e2010
  951. DTraceProviderBindings.node`usdt_fire_probe+0x32
  952. DTraceProviderBindings.node`_ZN4node11DTraceProbe5_fireEN2v85LocalINS1_5ValueEEE+0x32d
  953. DTraceProviderBindings.node`_ZN4node11DTraceProbe4FireERKN2v89ArgumentsE+0x77
  954. << internal code >>
  955. (anon) as (anon) at /root/node-bunyan/lib/bunyan.js position 40484
  956. << adaptor >>
  957. (anon) as doit at /root/my-prog.js position 360
  958. (anon) as list.ontimeout at timers.js position 4960
  959. << adaptor >>
  960. << internal >>
  961. << entry >>
  962. node`_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb+0x101
  963. node`_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb+0xcb
  964. node`_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE+0xf0
  965. node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_8FunctionEEEiPNS1_INS0_5ValueEEE+0x11f
  966. node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_6StringEEEiPNS1_INS0_5ValueEEE+0x66
  967. node`_ZN4node9TimerWrap9OnTimeoutEP10uv_timer_si+0x63
  968. node`uv__run_timers+0x66
  969. node`uv__run+0x1b
  970. node`uv_run+0x17
  971. node`_ZN4node5StartEiPPc+0x1d0
  972. node`main+0x1b
  973. node`_start+0x83
  974. node`0x87e2010
  975. DTraceProviderBindings.node`usdt_fire_probe+0x32
  976. DTraceProviderBindings.node`_ZN4node11DTraceProbe5_fireEN2v85LocalINS1_5ValueEEE+0x32d
  977. DTraceProviderBindings.node`_ZN4node11DTraceProbe4FireERKN2v89ArgumentsE+0x77
  978. << internal code >>
  979. (anon) as (anon) at /root/node-bunyan/lib/bunyan.js position 40484
  980. << adaptor >>
  981. (anon) as doit at /root/my-prog.js position 360
  982. (anon) as list.ontimeout at timers.js position 4960
  983. << adaptor >>
  984. << internal >>
  985. << entry >>
  986. node`_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb+0x101
  987. node`_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb+0xcb
  988. node`_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE+0xf0
  989. node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_8FunctionEEEiPNS1_INS0_5ValueEEE+0x11f
  990. node`_ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_6StringEEEiPNS1_INS0_5ValueEEE+0x66
  991. node`_ZN4node9TimerWrap9OnTimeoutEP10uv_timer_si+0x63
  992. node`uv__run_timers+0x66
  993. node`uv__run+0x1b
  994. node`uv_run+0x17
  995. node`_ZN4node5StartEiPPc+0x1d0
  996. node`main+0x1b
  997. node`_start+0x83
  998. ```
  999. # Runtime environments
  1000. Node-bunyan supports running in a few runtime environments:
  1001. - [Node.js](https://nodejs.org/)
  1002. - [Browserify](http://browserify.org/): See the
  1003. [Browserify section](#browserify) below.
  1004. - [Webpack](https://webpack.github.io/): See the [Webpack section](#webpack) below.
  1005. - [NW.js](http://nwjs.io/)
  1006. Support for other runtime environments is welcome. If you have suggestions,
  1007. fixes, or mentions that node-bunyan already works in some other JavaScript
  1008. runtime, please open an [issue](https://github.com/trentm/node-bunyan/issues/new)
  1009. or a pull request.
  1010. The primary target is Node.js. It is the only environment in which I
  1011. regularly test. If you have suggestions for how to automate testing for other
  1012. environments, I'd appreciate feedback on [this automated testing
  1013. issue](https://github.com/trentm/node-bunyan/issues/342).
  1014. ## Browserify
  1015. As the [Browserify](http://browserify.org/) site says it "lets you
  1016. `require('modules')` in the browser by bundling up all of your dependencies."
  1017. It is a build tool to run on your node.js script to bundle up your script and
  1018. all its node.js dependencies into a single file that is runnable in the
  1019. browser via:
  1020. ```html
  1021. <script src="play.browser.js"></script>
  1022. ```
  1023. As of version 1.1.0, node-bunyan supports being run via Browserify. The
  1024. default [stream](#streams) when running in the browser is one that emits
  1025. raw log records to `console.log/info/warn/error`.
  1026. Here is a quick example showing you how you can get this working for your
  1027. script.
  1028. 1. Get browserify and bunyan installed in your module:
  1029. ```sh
  1030. $ npm install browserify bunyan
  1031. ```
  1032. 2. An example script using Bunyan, "play.js":
  1033. ```js
  1034. var bunyan = require('bunyan');
  1035. var log = bunyan.createLogger({name: 'play', level: 'debug'});
  1036. log.trace('this one does not emit');
  1037. log.debug('hi on debug'); // console.log
  1038. log.info('hi on info'); // console.info
  1039. log.warn('hi on warn'); // console.warn
  1040. log.error('hi on error'); // console.error
  1041. ```
  1042. 3. Build this into a bundle to run in the browser, "play.browser.js":
  1043. ```sh
  1044. $ ./node_modules/.bin/browserify play.js -o play.browser.js
  1045. ```
  1046. 4. Put that into an HTML file, "play.html":
  1047. ```html
  1048. <!DOCTYPE html>
  1049. <html>
  1050. <head>
  1051. <meta charset="utf-8">
  1052. <script src="play.browser.js"></script>
  1053. </head>
  1054. <body>
  1055. <div>hi</div>
  1056. </body>
  1057. </html>
  1058. ```
  1059. 5. Open that in your browser and open your browser console:
  1060. ```sh
  1061. $ open play.html
  1062. ```
  1063. Here is what it looks like in Firefox's console: ![Bunyan + Browserify in the
  1064. Firefox console](./docs/img/bunyan.browserify.png)
  1065. For some, the raw log records might not be desired. To have a rendered log line
  1066. you'll want to add your own stream, starting with something like this:
  1067. ```js
  1068. var bunyan = require('./lib/bunyan');
  1069. function MyRawStream() {}
  1070. MyRawStream.prototype.write = function (rec) {
  1071. console.log('[%s] %s: %s',
  1072. rec.time.toISOString(),
  1073. bunyan.nameFromLevel[rec.level],
  1074. rec.msg);
  1075. }
  1076. var log = bunyan.createLogger({
  1077. name: 'play',
  1078. streams: [
  1079. {
  1080. level: 'info',
  1081. stream: new MyRawStream(),
  1082. type: 'raw'
  1083. }
  1084. ]
  1085. });
  1086. log.info('hi on info');
  1087. ```
  1088. ## Webpack
  1089. Webpack can work with the same example Browserify above. To do this, we need to make webpack ignore optional files:
  1090. Create "empty_shim.js":
  1091. ```javascript
  1092. // This is an empty shim for things that should be not be included in webpack
  1093. ```
  1094. Now tell webpack to use this file for
  1095. [optional dependencies](https://webpack.github.io/docs/configuration.html#resolve-alias)
  1096. in your "webpack.config.js":
  1097. ```
  1098. resolve: {
  1099. // These shims are needed for bunyan
  1100. alias: {
  1101. 'dtrace-provider': '/path/to/shim/empty_shim.js',
  1102. fs: '/path/to/shim/empty_shim.js',
  1103. 'safe-json-stringify': '/path/to/shim/empty_shim.js',
  1104. mv: '/path/to/shim/empty_shim.js',
  1105. 'source-map-support': '/path/to/shim/empty_shim.js'
  1106. }
  1107. }
  1108. ```
  1109. Now webpack builds, ignoring these optional dependencies via shimming in an empty JS file!
  1110. # Versioning
  1111. All versions are `<major>.<minor>.<patch>` which will be incremented for
  1112. breaking backward compat and major reworks, new features without breaking
  1113. change, and bug fixes, respectively. tl;dr: [Semantic
  1114. versioning](http://semver.org/).
  1115. # License
  1116. [MIT](./LICENSE.txt).
  1117. # See Also
  1118. See the [user-maintained list of Bunyan-related software in the Bunyan
  1119. wiki](https://github.com/trentm/node-bunyan/wiki/Awesome-Bunyan).