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:
Trent Mick 2012-06-21 14:49:04 -07:00
parent 0047bc060f
commit 37a1447f22
7 changed files with 84 additions and 70 deletions

View file

@ -13,17 +13,19 @@
recent, and thus hopefully relevant, log messages. (by @dapsays,
github.com/davepacheco)
Potential uses: Live debugging
if a running process could inspect those messages. One could dump recent
log messages at a finer log level than is typically logged on
Potential uses: Live debugging if a running process could inspect those
messages. One could dump recent log messages at a finer log level than is
typically logged on
[`uncaughtException`](http://nodejs.org/docs/latest/api/all.html#all_event_uncaughtexception).
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
var log = new bunyan({
name: "foo",
raw: true,
stream: ringbuffer,
level: "debug"
name: 'foo',
streams: [{
type: 'raw',
stream: ringbuffer,
level: 'debug'
}]
});
log.info('hello world');
@ -40,16 +42,18 @@
}
var log = new Logger({
name: 'mylog',
stream: new Collector(),
raw: true
streams: [{
type: 'raw',
stream: new Collector()
}]
});
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.
- Add test/corpus/*.log files (accidentally excluded) so that test suite
works(!).
- Add test/corpus/*.log files (accidentally excluded) so the test suite
actually works(!).
## bunyan 0.8.0

View file

@ -10,8 +10,8 @@ Also: log4j is way more than you need.
# Current Status
Basic functionality there. Still a fair amount of planned work, but I'm using
it for some production services.
Solid core functionality is there. Joyent is using this for a number of
production services.
Currently supports node 0.4+, but I'll probably make the jump to node 0.6+ as a
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
"stream", "level" and "raw" options (internal converted to a
`Logger.streams`):
"stream" and "level" options (internal converted to a `Logger.streams`):
var log = new Logger({
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:
- `type`: Typically implied. E.g. "stream" or "file". See supported types
below.
- `type`: One of "stream", "file" or "raw". See below. Often this is
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
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
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:
- `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
appending. E.g.:
@ -463,6 +465,14 @@ Supported stream types are:
// 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
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
@ -475,10 +485,18 @@ To use a RingBuffer:
var bunyan = require('bunyan');
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
var log = new bunyan({
name: "foo",
raw: true,
stream: ringbuffer,
level: "debug"
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');
@ -495,11 +513,13 @@ This example emits:
v: 0 } ]
# License
MIT.
# Future
See "TODO.md".

View file

@ -27,7 +27,7 @@ var log = new Logger({
{
level: 'info',
stream: new MyRawStream(),
raw: true
type: 'raw'
},
]
});

View file

@ -3,9 +3,11 @@ var bunyan = require('..');
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
var log = new bunyan({
name: 'foo',
raw: true,
stream: ringbuffer,
level: 'debug'
streams: [{
type: 'raw',
stream: ringbuffer,
level: 'debug'
}]
});
log.info('hello world');

View file

@ -175,13 +175,17 @@ function resolveLevel(nameOrNum) {
*
* @param options {Object} See documentation for full details. At minimum
* this must include a 'name' string key. Configuration keys:
* - streams: specify the logger output streams. This is an array of
* objects of the form:
* {
* 'level': 'info', // optional, "info" default
* 'stream': process.stdout, // 'stream' or "path" is required
* 'closeOnExit': false // optional, default depends
* }
* - `streams`: specify the logger output streams. This is an array of
* objects with these fields:
* - `type`: The stream type. See README.md for full details.
* Often this is implied by the other fields. Examples are
* "file", "stream" and "raw".
* - `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.
* - `level`: set the level for a single output stream (cannot be used
* with `streams`)
@ -300,6 +304,7 @@ function Logger(options, _childOptions, _childSimple) {
s.type = 'file'
}
}
s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`.
if (s.level) {
s.level = resolveLevel(s.level);
@ -310,8 +315,6 @@ function Logger(options, _childOptions, _childSimple) {
self._level = s.level;
}
s.raw = !!s.raw;
switch (s.type) {
case 'stream':
if (!s.closeOnExit) {
@ -334,6 +337,11 @@ function Logger(options, _childOptions, _childSimple) {
}
}
break;
case 'raw':
if (!s.closeOnExit) {
s.closeOnExit = false;
}
break;
default:
throw new TypeError('unknown stream type "' + s.type + '"');
}
@ -362,8 +370,7 @@ function Logger(options, _childOptions, _childSimple) {
type: 'stream',
stream: options.stream,
closeOnExit: false,
level: (options.level ? resolveLevel(options.level) : INFO),
raw: (options.raw ? options.raw : false)
level: (options.level ? resolveLevel(options.level) : INFO)
});
} else if (options.streams) {
options.streams.forEach(addStream);
@ -372,8 +379,7 @@ function Logger(options, _childOptions, _childSimple) {
type: 'stream',
stream: process.stdout,
closeOnExit: false,
level: (options.level ? resolveLevel(options.level) : INFO),
raw: (options.raw ? options.raw : false)
level: (options.level ? resolveLevel(options.level) : INFO)
});
}
if (options.serializers) {
@ -683,8 +689,8 @@ Logger.prototype._emit = function (rec) {
for (i = 0; i < this.streams.length; i++) {
var s = this.streams[i];
if (s.level <= level) {
xxx('writing log rec "%s" to "%s" stream (%s, %d <= %d): %j',
obj.msg, s.type, (s.raw ? 'raw' : 'not raw'), s.level, level, obj);
xxx('writing log rec "%s" to "%s" stream (%d <= %d): %j',
obj.msg, s.type, s.level, level, obj);
s.stream.write(s.raw ? obj : str);
}
};

View file

@ -1,7 +1,7 @@
/*
* 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;
@ -26,7 +26,7 @@ test('raw stream', function (t) {
streams: [
{
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) {
var rawRecs = [];
var nonRawRecs = [];
@ -67,7 +49,7 @@ test('raw streams and regular streams can mix', function (t) {
streams: [
{
stream: new CapturingStream(rawRecs),
raw: true
type: 'raw'
},
{
stream: new CapturingStream(nonRawRecs)
@ -98,7 +80,7 @@ test('child adding a non-raw stream works', function (t) {
streams: [
{
stream: new CapturingStream(parentRawRecs),
raw: true
type: 'raw'
}
]
});
@ -107,7 +89,7 @@ test('child adding a non-raw stream works', function (t) {
streams: [
{
stream: new CapturingStream(rawRecs),
raw: true
type: 'raw'
},
{
stream: new CapturingStream(nonRawRecs)

View file

@ -11,7 +11,7 @@ var log1 = new Logger({
streams: [
{
stream: ringbuffer,
raw: true,
type: 'raw',
level: 'info'
}
]