add ring buffer stream
This commit is contained in:
parent
f8de9a35d5
commit
f1996fccef
5 changed files with 133 additions and 1 deletions
30
README.md
30
README.md
|
@ -459,6 +459,36 @@ Supported stream types are:
|
|||
// Handle stream write or create error here.
|
||||
});
|
||||
|
||||
Bunyan comes with a special stream called a RingBuffer which keeps the last N
|
||||
records in memory and does *not* write the data anywhere else. One common
|
||||
strategy is to log 'info' and higher to a normal log file but log all records
|
||||
(including 'trace') to a ringbuffer that you can access via a debugger, or your
|
||||
own HTTP interface, or a post-mortem facility like MDB or node-panic.
|
||||
|
||||
To use a RingBuffer:
|
||||
|
||||
/* Create a ring buffer that stores the last 100 entries. */
|
||||
var bunyan = require('bunyan');
|
||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||
var log = new bunyan({
|
||||
name: "foo",
|
||||
stream: ringbuffer,
|
||||
level: "debug"
|
||||
});
|
||||
|
||||
log.info('hello world');
|
||||
console.log(ringbuffer.entries);
|
||||
|
||||
This example emits:
|
||||
|
||||
[ { name: 'foo',
|
||||
hostname: '912d2b29',
|
||||
pid: 50346,
|
||||
level: 30,
|
||||
msg: 'hello world',
|
||||
time: '2012-06-19T21:34:19.906Z',
|
||||
v: 0 } ]
|
||||
|
||||
|
||||
# License
|
||||
|
||||
|
|
1
TODO.md
1
TODO.md
|
@ -15,7 +15,6 @@
|
|||
works *and* that an existing field in the parent is not *re-serialized*.
|
||||
- a "rolling-file" stream: but specifically by time, e.g. hourly. (MarkC
|
||||
requested)
|
||||
- ringBuffer stream
|
||||
- split out `bunyan` cli to a "bunyan" or "bunyan-reader" or "node-bunyan-reader"
|
||||
as the basis for tools to consume bunyan logs. It can grow indep of node-bunyan
|
||||
for generating the logs.
|
||||
|
|
11
examples/ringbuffer.js
Normal file
11
examples/ringbuffer.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* Create a ring buffer that stores the last 100 entries. */
|
||||
var bunyan = require('..');
|
||||
var ringbuffer = new bunyan.RingBuffer({ limit: 100 });
|
||||
var log = new bunyan({
|
||||
name: 'foo',
|
||||
stream: ringbuffer,
|
||||
level: 'debug'
|
||||
});
|
||||
|
||||
log.info('hello world');
|
||||
console.log(ringbuffer.entries);
|
|
@ -954,6 +954,58 @@ var errSerializer = Logger.stdSerializers.err = function err(err) {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* RingBuffer is a Writable Stream that just stores the last N entries in
|
||||
* memory.
|
||||
*
|
||||
* @param options {Object}, with the following fields:
|
||||
*
|
||||
* - limit: number of entries to keep in memory
|
||||
*/
|
||||
function RingBuffer(options) {
|
||||
this.limit = options && options.limit ? options.limit : 100;
|
||||
this.writable = true;
|
||||
this.entries = [];
|
||||
EventEmitter.call(this);
|
||||
}
|
||||
|
||||
util.inherits(RingBuffer, EventEmitter);
|
||||
|
||||
RingBuffer.prototype.write = function (str) {
|
||||
var json;
|
||||
|
||||
if (!this.writable)
|
||||
throw (new Error('RingBuffer has been ended already'));
|
||||
|
||||
try {
|
||||
json = JSON.parse(str);
|
||||
this.entries.push(json);
|
||||
} catch (ex) {
|
||||
this.entries.push(str);
|
||||
}
|
||||
|
||||
if (this.entries.length > this.limit)
|
||||
this.entries.shift();
|
||||
|
||||
return (true);
|
||||
};
|
||||
|
||||
RingBuffer.prototype.end = function () {
|
||||
if (arguments.length > 0)
|
||||
this.write.apply(this, Array.prototype.slice.call(arguments));
|
||||
this.writable = false;
|
||||
};
|
||||
|
||||
RingBuffer.prototype.destroy = function () {
|
||||
this.writable = false;
|
||||
this.emit('close');
|
||||
};
|
||||
|
||||
RingBuffer.prototype.destroySoon = function () {
|
||||
this.destroy();
|
||||
this.emit('close');
|
||||
};
|
||||
|
||||
|
||||
//---- Exports
|
||||
|
||||
|
@ -972,3 +1024,5 @@ module.exports.LOG_VERSION = LOG_VERSION;
|
|||
module.exports.createLogger = function createLogger(options) {
|
||||
return new Logger(options);
|
||||
};
|
||||
|
||||
module.exports.RingBuffer = RingBuffer;
|
||||
|
|
38
test/ringbuffer.test.js
Normal file
38
test/ringbuffer.test.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Test the RingBuffer output stream.
|
||||
*/
|
||||
|
||||
var test = require('tap').test;
|
||||
var Logger = require('../lib/bunyan');
|
||||
var ringbuffer = new Logger.RingBuffer({ 'limit': 5 });
|
||||
|
||||
var log1 = new Logger({
|
||||
name: 'log1',
|
||||
streams: [
|
||||
{
|
||||
stream: ringbuffer,
|
||||
level: 'info'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
test('ringbuffer', function (t) {
|
||||
log1.info('hello');
|
||||
log1.trace('there');
|
||||
log1.error('chucklebucket');
|
||||
t.equal(ringbuffer.entries.length, 2);
|
||||
t.equal(ringbuffer.entries[0]['msg'], 'hello');
|
||||
t.equal(ringbuffer.entries[1]['msg'], 'chucklebucket');
|
||||
log1.error('one');
|
||||
log1.error('two');
|
||||
log1.error('three');
|
||||
t.equal(ringbuffer.entries.length, 5);
|
||||
log1.error('four');
|
||||
t.equal(ringbuffer.entries.length, 5);
|
||||
t.equal(ringbuffer.entries[0]['msg'], 'chucklebucket');
|
||||
t.equal(ringbuffer.entries[1]['msg'], 'one');
|
||||
t.equal(ringbuffer.entries[2]['msg'], 'two');
|
||||
t.equal(ringbuffer.entries[3]['msg'], 'three');
|
||||
t.equal(ringbuffer.entries[4]['msg'], 'four');
|
||||
t.end();
|
||||
});
|
Loading…
Reference in a new issue