per issue #8 change the way a raw stream is handled
"raw" is now a stream "type" isntead of a separate attribute. The idea is that writing raw objects (instead of JSON-stringified stings) to, e.g. a file WriteStream isn't useful. So, lets re-use the stream "type" field instead of an additional "raw" field.
This commit is contained in:
parent
0047bc060f
commit
37a1447f22
7 changed files with 84 additions and 70 deletions
28
CHANGES.md
28
CHANGES.md
|
@ -13,17 +13,19 @@
|
||||||
recent, and thus hopefully relevant, log messages. (by @dapsays,
|
recent, and thus hopefully relevant, log messages. (by @dapsays,
|
||||||
github.com/davepacheco)
|
github.com/davepacheco)
|
||||||
|
|
||||||
Potential uses: Live debugging
|
Potential uses: Live debugging if a running process could inspect those
|
||||||
if a running process could inspect those messages. One could dump recent
|
messages. One could dump recent log messages at a finer log level than is
|
||||||
log messages at a finer log level than is typically logged on
|
typically logged on
|
||||||
[`uncaughtException`](http://nodejs.org/docs/latest/api/all.html#all_event_uncaughtexception).
|
[`uncaughtException`](http://nodejs.org/docs/latest/api/all.html#all_event_uncaughtexception).
|
||||||
|
|
||||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||||
var log = new bunyan({
|
var log = new bunyan({
|
||||||
name: "foo",
|
name: 'foo',
|
||||||
raw: true,
|
streams: [{
|
||||||
stream: ringbuffer,
|
type: 'raw',
|
||||||
level: "debug"
|
stream: ringbuffer,
|
||||||
|
level: 'debug'
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info('hello world');
|
log.info('hello world');
|
||||||
|
@ -40,16 +42,18 @@
|
||||||
}
|
}
|
||||||
var log = new Logger({
|
var log = new Logger({
|
||||||
name: 'mylog',
|
name: 'mylog',
|
||||||
stream: new Collector(),
|
streams: [{
|
||||||
raw: true
|
type: 'raw',
|
||||||
|
stream: new Collector()
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
See "examples/raw-stream.js". I expect raw streams to be useful for
|
See "examples/raw-stream.js". I expect raw streams to be useful for
|
||||||
piping Bunyan logging to separate services (e.g. <http://log.ly>,
|
piping Bunyan logging to separate services (e.g. <http://www.loggly.com/>,
|
||||||
<https://github.com/etsy/statsd>) or to separate in-process handling.
|
<https://github.com/etsy/statsd>) or to separate in-process handling.
|
||||||
|
|
||||||
- Add test/corpus/*.log files (accidentally excluded) so that test suite
|
- Add test/corpus/*.log files (accidentally excluded) so the test suite
|
||||||
works(!).
|
actually works(!).
|
||||||
|
|
||||||
|
|
||||||
## bunyan 0.8.0
|
## bunyan 0.8.0
|
||||||
|
|
50
README.md
50
README.md
|
@ -10,8 +10,8 @@ Also: log4j is way more than you need.
|
||||||
|
|
||||||
# Current Status
|
# Current Status
|
||||||
|
|
||||||
Basic functionality there. Still a fair amount of planned work, but I'm using
|
Solid core functionality is there. Joyent is using this for a number of
|
||||||
it for some production services.
|
production services.
|
||||||
|
|
||||||
Currently supports node 0.4+, but I'll probably make the jump to node 0.6+ as a
|
Currently supports node 0.4+, but I'll probably make the jump to node 0.6+ as a
|
||||||
base soonish.
|
base soonish.
|
||||||
|
@ -420,8 +420,7 @@ In general streams are specified with the "streams" option:
|
||||||
})
|
})
|
||||||
|
|
||||||
For convenience, if there is only one stream, it can specified with the
|
For convenience, if there is only one stream, it can specified with the
|
||||||
"stream", "level" and "raw" options (internal converted to a
|
"stream" and "level" options (internal converted to a `Logger.streams`):
|
||||||
`Logger.streams`):
|
|
||||||
|
|
||||||
var log = new Logger({
|
var log = new Logger({
|
||||||
name: "foo",
|
name: "foo",
|
||||||
|
@ -434,19 +433,22 @@ If none are specified, the default is a stream on `process.stdout` at the
|
||||||
|
|
||||||
`Logger.streams` is an array of stream objects with the following attributes:
|
`Logger.streams` is an array of stream objects with the following attributes:
|
||||||
|
|
||||||
- `type`: Typically implied. E.g. "stream" or "file". See supported types
|
- `type`: One of "stream", "file" or "raw". See below. Often this is
|
||||||
below.
|
implied from the other arguments.
|
||||||
|
- `path`: A file path for a file stream. If `path` is given and `type` is
|
||||||
|
not specified, then `type` will be set to "file".
|
||||||
- `stream`: This is the "Writable Stream", e.g. a std handle or an open
|
- `stream`: This is the "Writable Stream", e.g. a std handle or an open
|
||||||
file write stream.
|
file write stream. If `stream` is given and `type` is not specified, then
|
||||||
|
`type` will be set to "stream".
|
||||||
- `level`: The level at which logging to this stream is enabled. If not
|
- `level`: The level at which logging to this stream is enabled. If not
|
||||||
specified it defaults to INFO.
|
specified it defaults to INFO.
|
||||||
- `raw`: A boolean indicating if the `write()` method of this stream should
|
|
||||||
be given the raw log record object instead of the JSON-stringified
|
|
||||||
string. See "examples/raw-stream.js".
|
|
||||||
|
|
||||||
Supported stream types are:
|
Supported stream types are:
|
||||||
|
|
||||||
- `stream`: A "stream" argument is given.
|
- `stream`: A plain ol' node.js [Writable
|
||||||
|
Stream](http://nodejs.org/docs/latest/api/all.html#writable_Stream).
|
||||||
|
A "stream" (the writeable stream) value is required.
|
||||||
|
|
||||||
- `file`: A "path" argument is given. Bunyan will open this file for
|
- `file`: A "path" argument is given. Bunyan will open this file for
|
||||||
appending. E.g.:
|
appending. E.g.:
|
||||||
|
|
||||||
|
@ -463,6 +465,14 @@ Supported stream types are:
|
||||||
// Handle stream write or create error here.
|
// Handle stream write or create error here.
|
||||||
});
|
});
|
||||||
|
|
||||||
|
- `raw`: Similar to a "stream" writeable 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.
|
||||||
|
|
||||||
|
|
||||||
|
## RingBuffer Stream
|
||||||
|
|
||||||
Bunyan comes with a special stream called a RingBuffer which keeps the last N
|
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
|
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
|
strategy is to log 'info' and higher to a normal log file but log all records
|
||||||
|
@ -475,10 +485,18 @@ To use a RingBuffer:
|
||||||
var bunyan = require('bunyan');
|
var bunyan = require('bunyan');
|
||||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||||
var log = new bunyan({
|
var log = new bunyan({
|
||||||
name: "foo",
|
name: 'foo',
|
||||||
raw: true,
|
streams: [
|
||||||
stream: ringbuffer,
|
{
|
||||||
level: "debug"
|
level: 'info',
|
||||||
|
stream: process.stdout
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'trace',
|
||||||
|
type: 'raw', // use 'raw' to get raw log record objects
|
||||||
|
stream: ringbuffer
|
||||||
|
}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info('hello world');
|
log.info('hello world');
|
||||||
|
@ -495,11 +513,13 @@ This example emits:
|
||||||
v: 0 } ]
|
v: 0 } ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
MIT.
|
MIT.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Future
|
# Future
|
||||||
|
|
||||||
See "TODO.md".
|
See "TODO.md".
|
||||||
|
|
|
@ -27,7 +27,7 @@ var log = new Logger({
|
||||||
{
|
{
|
||||||
level: 'info',
|
level: 'info',
|
||||||
stream: new MyRawStream(),
|
stream: new MyRawStream(),
|
||||||
raw: true
|
type: 'raw'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,9 +3,11 @@ var bunyan = require('..');
|
||||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||||
var log = new bunyan({
|
var log = new bunyan({
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
raw: true,
|
streams: [{
|
||||||
stream: ringbuffer,
|
type: 'raw',
|
||||||
level: 'debug'
|
stream: ringbuffer,
|
||||||
|
level: 'debug'
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info('hello world');
|
log.info('hello world');
|
||||||
|
|
|
@ -175,13 +175,17 @@ function resolveLevel(nameOrNum) {
|
||||||
*
|
*
|
||||||
* @param options {Object} See documentation for full details. At minimum
|
* @param options {Object} See documentation for full details. At minimum
|
||||||
* this must include a 'name' string key. Configuration keys:
|
* this must include a 'name' string key. Configuration keys:
|
||||||
* - streams: specify the logger output streams. This is an array of
|
* - `streams`: specify the logger output streams. This is an array of
|
||||||
* objects of the form:
|
* objects with these fields:
|
||||||
* {
|
* - `type`: The stream type. See README.md for full details.
|
||||||
* 'level': 'info', // optional, "info" default
|
* Often this is implied by the other fields. Examples are
|
||||||
* 'stream': process.stdout, // 'stream' or "path" is required
|
* "file", "stream" and "raw".
|
||||||
* 'closeOnExit': false // optional, default depends
|
* - `level`: Defaults to "info".
|
||||||
* }
|
* - `path` or `stream`: The specify the file path or writeable
|
||||||
|
* stream to which log records are written. E.g.
|
||||||
|
* `stream: process.stdout`.
|
||||||
|
* - `closeOnExit` (boolean): Optional. Default is true for a
|
||||||
|
* "file" stream when `path` is given, false otherwise.
|
||||||
* See README.md for full details.
|
* See README.md for full details.
|
||||||
* - `level`: set the level for a single output stream (cannot be used
|
* - `level`: set the level for a single output stream (cannot be used
|
||||||
* with `streams`)
|
* with `streams`)
|
||||||
|
@ -300,6 +304,7 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
s.type = 'file'
|
s.type = 'file'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`.
|
||||||
|
|
||||||
if (s.level) {
|
if (s.level) {
|
||||||
s.level = resolveLevel(s.level);
|
s.level = resolveLevel(s.level);
|
||||||
|
@ -310,8 +315,6 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
self._level = s.level;
|
self._level = s.level;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.raw = !!s.raw;
|
|
||||||
|
|
||||||
switch (s.type) {
|
switch (s.type) {
|
||||||
case 'stream':
|
case 'stream':
|
||||||
if (!s.closeOnExit) {
|
if (!s.closeOnExit) {
|
||||||
|
@ -334,6 +337,11 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'raw':
|
||||||
|
if (!s.closeOnExit) {
|
||||||
|
s.closeOnExit = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new TypeError('unknown stream type "' + s.type + '"');
|
throw new TypeError('unknown stream type "' + s.type + '"');
|
||||||
}
|
}
|
||||||
|
@ -362,8 +370,7 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
type: 'stream',
|
type: 'stream',
|
||||||
stream: options.stream,
|
stream: options.stream,
|
||||||
closeOnExit: false,
|
closeOnExit: false,
|
||||||
level: (options.level ? resolveLevel(options.level) : INFO),
|
level: (options.level ? resolveLevel(options.level) : INFO)
|
||||||
raw: (options.raw ? options.raw : false)
|
|
||||||
});
|
});
|
||||||
} else if (options.streams) {
|
} else if (options.streams) {
|
||||||
options.streams.forEach(addStream);
|
options.streams.forEach(addStream);
|
||||||
|
@ -372,8 +379,7 @@ function Logger(options, _childOptions, _childSimple) {
|
||||||
type: 'stream',
|
type: 'stream',
|
||||||
stream: process.stdout,
|
stream: process.stdout,
|
||||||
closeOnExit: false,
|
closeOnExit: false,
|
||||||
level: (options.level ? resolveLevel(options.level) : INFO),
|
level: (options.level ? resolveLevel(options.level) : INFO)
|
||||||
raw: (options.raw ? options.raw : false)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (options.serializers) {
|
if (options.serializers) {
|
||||||
|
@ -683,8 +689,8 @@ Logger.prototype._emit = function (rec) {
|
||||||
for (i = 0; i < this.streams.length; i++) {
|
for (i = 0; i < this.streams.length; i++) {
|
||||||
var s = this.streams[i];
|
var s = this.streams[i];
|
||||||
if (s.level <= level) {
|
if (s.level <= level) {
|
||||||
xxx('writing log rec "%s" to "%s" stream (%s, %d <= %d): %j',
|
xxx('writing log rec "%s" to "%s" stream (%d <= %d): %j',
|
||||||
obj.msg, s.type, (s.raw ? 'raw' : 'not raw'), s.level, level, obj);
|
obj.msg, s.type, s.level, level, obj);
|
||||||
s.stream.write(s.raw ? obj : str);
|
s.stream.write(s.raw ? obj : str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Trent Mick. All rights reserved.
|
* Copyright (c) 2012 Trent Mick. All rights reserved.
|
||||||
*
|
*
|
||||||
* Test `raw: true` option on a Logger stream.
|
* Test `type: 'raw'` Logger streams.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var format = require('util').format;
|
var format = require('util').format;
|
||||||
|
@ -26,7 +26,7 @@ test('raw stream', function (t) {
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(recs),
|
stream: new CapturingStream(recs),
|
||||||
raw: true
|
type: 'raw'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -40,24 +40,6 @@ test('raw stream', function (t) {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test('raw stream (short constructor)', function (t) {
|
|
||||||
var recs = [];
|
|
||||||
|
|
||||||
var log = new Logger({
|
|
||||||
name: 'raw-stream-test',
|
|
||||||
stream: new CapturingStream(recs),
|
|
||||||
raw: true
|
|
||||||
});
|
|
||||||
log.info('first');
|
|
||||||
log.info({two: 'deux'}, 'second');
|
|
||||||
|
|
||||||
t.equal(recs.length, 2);
|
|
||||||
t.equal(typeof (recs[0]), 'object', 'first rec is an object');
|
|
||||||
t.equal(recs[1].two, 'deux', '"two" field made it through');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('raw streams and regular streams can mix', function (t) {
|
test('raw streams and regular streams can mix', function (t) {
|
||||||
var rawRecs = [];
|
var rawRecs = [];
|
||||||
var nonRawRecs = [];
|
var nonRawRecs = [];
|
||||||
|
@ -67,7 +49,7 @@ test('raw streams and regular streams can mix', function (t) {
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(rawRecs),
|
stream: new CapturingStream(rawRecs),
|
||||||
raw: true
|
type: 'raw'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(nonRawRecs)
|
stream: new CapturingStream(nonRawRecs)
|
||||||
|
@ -98,7 +80,7 @@ test('child adding a non-raw stream works', function (t) {
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(parentRawRecs),
|
stream: new CapturingStream(parentRawRecs),
|
||||||
raw: true
|
type: 'raw'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -107,7 +89,7 @@ test('child adding a non-raw stream works', function (t) {
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(rawRecs),
|
stream: new CapturingStream(rawRecs),
|
||||||
raw: true
|
type: 'raw'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
stream: new CapturingStream(nonRawRecs)
|
stream: new CapturingStream(nonRawRecs)
|
||||||
|
|
|
@ -11,7 +11,7 @@ var log1 = new Logger({
|
||||||
streams: [
|
streams: [
|
||||||
{
|
{
|
||||||
stream: ringbuffer,
|
stream: ringbuffer,
|
||||||
raw: true,
|
type: 'raw',
|
||||||
level: 'info'
|
level: 'info'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue