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.
|
// 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
|
# License
|
||||||
|
|
||||||
|
|
1
TODO.md
1
TODO.md
|
@ -15,7 +15,6 @@
|
||||||
works *and* that an existing field in the parent is not *re-serialized*.
|
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
|
- a "rolling-file" stream: but specifically by time, e.g. hourly. (MarkC
|
||||||
requested)
|
requested)
|
||||||
- ringBuffer stream
|
|
||||||
- split out `bunyan` cli to a "bunyan" or "bunyan-reader" or "node-bunyan-reader"
|
- 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
|
as the basis for tools to consume bunyan logs. It can grow indep of node-bunyan
|
||||||
for generating the logs.
|
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
|
//---- Exports
|
||||||
|
|
||||||
|
@ -972,3 +1024,5 @@ module.exports.LOG_VERSION = LOG_VERSION;
|
||||||
module.exports.createLogger = function createLogger(options) {
|
module.exports.createLogger = function createLogger(options) {
|
||||||
return new Logger(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