From 334e36cdfd5683e3f26c023e70a866231ebeabaf Mon Sep 17 00:00:00 2001 From: Andrei Neculau Date: Thu, 17 Apr 2014 14:37:44 +0200 Subject: [PATCH] fix #105: export addStream and addSerializers --- lib/bunyan.js | 208 +++++++++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 89 deletions(-) diff --git a/lib/bunyan.js b/lib/bunyan.js index f4b5c76..b1f686b 100644 --- a/lib/bunyan.js +++ b/lib/bunyan.js @@ -337,107 +337,25 @@ function Logger(options, _childOptions, _childSimple) { } // Helpers - function addStream(s) { - s = objCopy(s); - - // Implicit 'type' from other args. - var type = s.type; - if (!s.type) { - if (s.stream) { - s.type = 'stream'; - } else if (s.path) { - s.type = 'file' - } - } - s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`. - - if (s.level) { - s.level = resolveLevel(s.level); - } else if (options.level) { - s.level = resolveLevel(options.level); - } else { - s.level = INFO; - } - if (s.level < self._level) { - self._level = s.level; - } - - switch (s.type) { - case 'stream': - if (!s.closeOnExit) { - s.closeOnExit = false; - } - break; - case 'file': - if (!s.stream) { - s.stream = fs.createWriteStream(s.path, - {flags: 'a', encoding: 'utf8'}); - s.stream.on('error', function (err) { - self.emit('error', err, s); - }); - if (!s.closeOnExit) { - s.closeOnExit = true; - } - } else { - if (!s.closeOnExit) { - s.closeOnExit = false; - } - } - break; - case 'rotating-file': - assert.ok(!s.stream, - '"rotating-file" stream should not give a "stream"'); - assert.ok(s.path); - assert.ok(mv, '"rotating-file" stream type is not supported: ' - + 'missing "mv" module'); - s.stream = new RotatingFileStream(s); - if (!s.closeOnExit) { - s.closeOnExit = true; - } - break; - case 'raw': - if (!s.closeOnExit) { - s.closeOnExit = false; - } - break; - default: - throw new TypeError('unknown stream type "' + s.type + '"'); - } - - self.streams.push(s); - } - - function addSerializers(serializers) { - if (!self.serializers) { - self.serializers = {}; - } - Object.keys(serializers).forEach(function (field) { - var serializer = serializers[field]; - if (typeof (serializer) !== 'function') { - throw new TypeError(format( - 'invalid serializer for "%s" field: must be a function', - field)); - } else { - self.serializers[field] = serializer; - } - }); - } // Handle *config* options (i.e. options that are not just plain data // for log records). if (options.stream) { - addStream({ + self.addStream({ type: 'stream', stream: options.stream, closeOnExit: false, level: (options.level ? resolveLevel(options.level) : INFO) }); } else if (options.streams) { - options.streams.forEach(addStream); + options.streams.forEach(function(s) { + s.level = s.level || s.level; + self.addStream(s); + }); } else if (parent && options.level) { this.level(options.level); } else if (!parent) { - addStream({ + self.addStream({ type: 'stream', stream: process.stdout, closeOnExit: false, @@ -445,7 +363,7 @@ function Logger(options, _childOptions, _childSimple) { }); } if (options.serializers) { - addSerializers(options.serializers); + self.addSerializers(options.serializers); } if (options.src) { this.src = true; @@ -480,6 +398,118 @@ function Logger(options, _childOptions, _childSimple) { util.inherits(Logger, EventEmitter); +/** + * Add a stream + * + * @param stream {Object}. Object 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. + */ +Logger.prototype.addStream = function(s) { + var self = this; + + s = objCopy(s); + + // Implicit 'type' from other args. + var type = s.type; + if (!s.type) { + if (s.stream) { + s.type = 'stream'; + } else if (s.path) { + s.type = 'file' + } + } + s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`. + + if (s.level) { + s.level = resolveLevel(s.level); + } else { + s.level = INFO; + } + if (s.level < self._level) { + self._level = s.level; + } + + switch (s.type) { + case 'stream': + if (!s.closeOnExit) { + s.closeOnExit = false; + } + break; + case 'file': + if (!s.stream) { + s.stream = fs.createWriteStream(s.path, + {flags: 'a', encoding: 'utf8'}); + s.stream.on('error', function (err) { + self.emit('error', err, s); + }); + if (!s.closeOnExit) { + s.closeOnExit = true; + } + } else { + if (!s.closeOnExit) { + s.closeOnExit = false; + } + } + break; + case 'rotating-file': + assert.ok(!s.stream, + '"rotating-file" stream should not give a "stream"'); + assert.ok(s.path); + assert.ok(mv, '"rotating-file" stream type is not supported: ' + + 'missing "mv" module'); + s.stream = new RotatingFileStream(s); + if (!s.closeOnExit) { + s.closeOnExit = true; + } + break; + case 'raw': + if (!s.closeOnExit) { + s.closeOnExit = false; + } + break; + default: + throw new TypeError('unknown stream type "' + s.type + '"'); + } + + self.streams.push(s); +} + + +/** + * Add serializers + * + * @param serializers {Object} Optional. Object mapping log record field names to + * serializing functions. See README.md for details. + */ +Logger.prototype.addSerializers = function(serializers) { + var self = this; + + if (!self.serializers) { + self.serializers = {}; + } + Object.keys(serializers).forEach(function (field) { + var serializer = serializers[field]; + if (typeof (serializer) !== 'function') { + throw new TypeError(format( + 'invalid serializer for "%s" field: must be a function', + field)); + } else { + self.serializers[field] = serializer; + } + }); +} + + + /** * Create a child logger, typically to add a few log record fields. *