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
26
CHANGES.md
26
CHANGES.md
|
@ -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,
|
||||
name: 'foo',
|
||||
streams: [{
|
||||
type: 'raw',
|
||||
stream: ringbuffer,
|
||||
level: "debug"
|
||||
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
|
||||
|
|
50
README.md
50
README.md
|
@ -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".
|
||||
|
|
|
@ -27,7 +27,7 @@ var log = new Logger({
|
|||
{
|
||||
level: 'info',
|
||||
stream: new MyRawStream(),
|
||||
raw: true
|
||||
type: 'raw'
|
||||
},
|
||||
]
|
||||
});
|
||||
|
|
|
@ -3,9 +3,11 @@ var bunyan = require('..');
|
|||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||
var log = new bunyan({
|
||||
name: 'foo',
|
||||
raw: true,
|
||||
streams: [{
|
||||
type: 'raw',
|
||||
stream: ringbuffer,
|
||||
level: 'debug'
|
||||
}]
|
||||
});
|
||||
|
||||
log.info('hello world');
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -11,7 +11,7 @@ var log1 = new Logger({
|
|||
streams: [
|
||||
{
|
||||
stream: ringbuffer,
|
||||
raw: true,
|
||||
type: 'raw',
|
||||
level: 'info'
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue