From 3aa990c35dc432aa1c0c887f53115614d8e8a9fb Mon Sep 17 00:00:00 2001 From: indexzero Date: Thu, 29 Oct 2015 00:32:42 -0700 Subject: [PATCH] [refactor api] Added `Logger.prototype.configure` which now contains all logic previously in the `winston.Logger` constructor function. [api] `winston.Logger` constructor function and `Logger.prototype.configure` set filters in addition to rewriters. --- README.md | 40 +++++++++++++++++++++-- lib/winston/logger.js | 76 +++++++++++++++++++++++++------------------ test/logger-test.js | 22 +++++++++++++ 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 14e0dc1aa..a932eaf54 100644 --- a/README.md +++ b/README.md @@ -95,10 +95,35 @@ You can work with this logger in the same way that you work with the default log // Adding / Removing Transports // (Yes It's chainable) // - logger.add(winston.transports.File) - .remove(winston.transports.Console); + logger + .add(winston.transports.File) + .remove(winston.transports.Console); ``` +You can also wholesale reconfigure a `winston.Logger` instance using the `configure` method: + +``` js + var logger = new winston.Logger({ + level: 'info', + transports: [ + new (winston.transports.Console)(), + new (winston.transports.File)({ filename: 'somefile.log' }) + ] + }); + + // + // Replaces the previous transports with those in the + // new configuration wholesale. + // + logger.configure({ + level: 'verbose', + transports: [ + new require('winston-daily-rotate-file')(opts) + ] + }); +``` + + ### Logging with Metadata In addition to logging string messages, winston will also optionally log additional JSON metadata objects. Adding metadata is simple: @@ -641,6 +666,17 @@ Configuring output for this style is easy, just use the `.cli()` method on `wins ### Filters and Rewriters Filters allow modifying the contents of **log messages**, and Rewriters allow modifying the contents of **log meta** e.g. to mask data that should not appear in logs. +Both filters and rewriters are simple Arrays of functions which can be provided when creating a `new winston.Logger(options)`. e.g.: + +``` js +var logger = new winston.Logger({ + rewriters: [function (level, msg, meta) { /* etc etc */ }] + filters: [function (msg, meta, level) { /* etc etc */ }] +}) +``` + +Like any Array they can also be modified at runtime with no adverse side-effects to the `winston` internals. + ``` js logger.filters.push(function(msg, meta, level) { return meta.production diff --git a/lib/winston/logger.js b/lib/winston/logger.js index 85aeebfd6..49984f6eb 100755 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -22,10 +22,41 @@ var events = require('events'), // var Logger = exports.Logger = function (options) { events.EventEmitter.call(this); + this.configure(options); +}; + +// +// Inherit from `events.EventEmitter`. +// +util.inherits(Logger, events.EventEmitter); + +// +// ### function configure (options) +// This will wholesale reconfigure this instance by: +// 1. Resetting all transports. Older transports will be removed implicitly. +// 2. Set all other options including levels, colors, rewriters, filters, +// exceptionHandlers, etc. +// +Logger.prototype.configure = function (options) { + var self = this; + + // + // If we have already been setup with transports + // then remove them before proceeding. + // + if (Array.isArray(this._names) && this._names.length) { + this.clear(); + } + options = options || {}; + this.transports = {}; + this._names = []; - var self = this, - handleExceptions = false; + if (options.transports) { + options.transports.forEach(function (transport) { + self.add(transport, null, true); + }); + } // // Set Levels and default logging level @@ -47,40 +78,23 @@ var Logger = exports.Logger = function (options) { : true; // - // Setup other intelligent default settings. + // Setup internal state as empty Objects even though it is + // defined lazily later to ensure a strong existential API contract. // - this.transports = {}; - this.rewriters = []; - this.filters = []; this.exceptionHandlers = {}; this.profilers = {}; - this._names = []; - this._hnames = []; - - if (options.transports) { - options.transports.forEach(function (transport) { - self.add(transport, null, true); - - if (transport.handleExceptions) { - handleExceptions = true; - } - }); - } - if (Array.isArray(options.rewriters)) { - this.rewriters = options.rewriters; - } + ['rewriters', 'filters'].forEach(function (kind) { + self[kind] = Array.isArray(options[kind]) + ? options[kind] + : []; + }); if (options.exceptionHandlers) { this.handleExceptions(options.exceptionHandlers); } }; -// -// Inherit from `events.EventEmitter`. -// -util.inherits(Logger, events.EventEmitter); - // // ### function log (level, msg, [meta], callback) // #### @level {string} Level at which to log the message. @@ -106,7 +120,7 @@ Logger.prototype.log = function (level) { msg = new Array(this.levelLength - level.length + 1).join(' ') + msg; } - function onError (err) { + function onError(err) { if (callback) { callback(err); } @@ -115,7 +129,6 @@ Logger.prototype.log = function (level) { } } - if (Object.keys(this.transports).length === 0) { return onError(new Error('Cannot log with no transports.')); } @@ -185,7 +198,6 @@ Logger.prototype.log = function (level) { } async.forEach(this._names, emit, cb); - return this; }; @@ -230,7 +242,7 @@ Logger.prototype.query = function (options, callback) { // Helper function to accumulate the results from // `queryTransport` into the `results`. // - function addResults (transport, next) { + function addResults(transport, next) { queryTransport(transport, function (err, result) { // // queryTransport could potentially invoke the callback @@ -456,9 +468,9 @@ Logger.prototype.add = function (transport, options, created) { // Remove all transports from this instance // Logger.prototype.clear = function () { - for (var name in this.transports) { + Object.keys(this.transports).forEach(function (name) { this.remove({ name: name }); - } + }, this); }; // diff --git a/test/logger-test.js b/test/logger-test.js index 31a7b0cbd..bc3773441 100755 --- a/test/logger-test.js +++ b/test/logger-test.js @@ -65,7 +65,29 @@ vows.describe('winton/logger').addBatch({ assert.equal(level, 'info'); assert.equal(msg, 'test message'); } + } + } + } +}).addBatch({ + "An instance of winston.Logger": { + topic: new (winston.Logger)({ transports: [new (winston.transports.Console)({ level: 'info' })] }), + "the configure() method": { + "with no options": function (logger) { + assert.equal(Object.keys(logger.transports).length, 1); + assert.deepEqual(logger._names, ['console']); + logger.configure(); + assert.equal(Object.keys(logger.transports).length, 0); + assert.deepEqual(logger._names, []); }, + "with options { transports }": function (logger) { + assert.equal(Object.keys(logger.transports).length, 0); + assert.deepEqual(logger._names, []); + logger.configure({ + transports: [new winston.transports.Console({ level: 'verbose' })] + }); + assert.equal(Object.keys(logger.transports).length, 1); + assert.deepEqual(logger._names, ['console']); + } } } }).addBatch({