From 270be866e155cfa8471e5b362836d55f0c8d56ab Mon Sep 17 00:00:00 2001 From: indexzero Date: Tue, 6 Jan 2015 11:29:34 -0700 Subject: [PATCH] [api] Allow for transports to be removed by their string name [test fix] Add test coverage for multiple transports of the same type added in #187. [doc] Document using multiple transports of the same type Fixes #101 (again), Fixes #301 --- README.md | 38 ++++++++++++++++++++++++++++- lib/winston/logger.js | 8 +++--- lib/winston/transports/transport.js | 12 ++++----- test/logger-test.js | 32 +++++++++++++++++++----- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5a2bf5459..62430b445 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ There are two different ways to use winston: directly via the default logger, or * [Using the Default Logger](#using-the-default-logger) * [Instantiating your own Logger](#instantiating-your-own-logger) * [Logging with Metadata](#logging-with-metadata) - * [String interpolation ](#string-interpolation) + * [String interpolation](#string-interpolation) * [Transports](https://github.com/flatiron/winston/blob/master/docs/transports.md) + * [Multiple transports of the same type](#multiple-transports-of-the-same-type) * [Profiling](#profiling) * [Streaming Logs](#streaming-logs) * [Querying Logs](#querying-logs) @@ -104,6 +105,41 @@ The way these objects are stored varies from transport to transport (to best sup 1. __Console:__ Logged via util.inspect(meta) 2. __File:__ Logged via util.inspect(meta) +## Multiple transports of the same type + +It is possible to use multiple transports of the same type e.g. `winston.transports.File` by passing in a custom `name` when you construct the transport. + +``` js +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.File)({ + name: 'info-file', + filename: 'filelog-info.log', + level: 'info' + }), + new (winston.transports.File)({ + name: 'error-file', + filename: 'filelog-error.log', + level: 'error' + }) + ] +}); +``` + +If you later want to remove one of these transports you can do so by using the string name. e.g.: + +``` js +logger.remove('info-file'); +``` + +In this example one could also remove by passing in the instance of the Transport itself. e.g. this is equivalent to the string example above; + +``` +// Notice it was first in the Array above +var infoFile = logger.transports[0]; +logger.remove(infoFile); +``` + ## Profiling In addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger: diff --git a/lib/winston/logger.js b/lib/winston/logger.js index b6f188354..bcf3b8347 100755 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -141,7 +141,7 @@ Logger.prototype.log = function (level) { } } - + if (Object.keys(this.transports).length === 0) { return onError(new Error('Cannot log with no transports.')); } @@ -484,11 +484,13 @@ Logger.prototype.clear = function () { // // ### function remove (transport) -// #### @transport {Transport} Transport to remove. +// #### @transport {Transport|String} Transport or Name to remove. // Removes a transport of the specified type from this instance. // Logger.prototype.remove = function (transport) { - var name = transport.name || transport.prototype.name; + var name = typeof transport !== 'string' + ? transport.name || transport.prototype.name + : transport; if (!this.transports[name]) { throw new Error('Transport ' + name + ' not attached to this instance'); diff --git a/lib/winston/transports/transport.js b/lib/winston/transports/transport.js index 598e07b7d..36bba2e02 100644 --- a/lib/winston/transports/transport.js +++ b/lib/winston/transports/transport.js @@ -18,14 +18,14 @@ var events = require('events'), var Transport = exports.Transport = function (options) { events.EventEmitter.call(this); - options = options || {}; - this.level = options.level === undefined ? 'info' : options.level; - this.silent = options.silent || false; - this.raw = options.raw || false; - this.name = options.name || this.name; + options = options || {}; + this.level = options.level === undefined ? 'info' : options.level; + this.silent = options.silent || false; + this.raw = options.raw || false; + this.name = options.name || this.name; this.handleExceptions = options.handleExceptions || false; - this.exceptionsLevel = options.exceptionsLevel || 'error'; + this.exceptionsLevel = options.exceptionsLevel || 'error'; }; // diff --git a/test/logger-test.js b/test/logger-test.js index e2525dbf7..860fb4d25 100755 --- a/test/logger-test.js +++ b/test/logger-test.js @@ -381,14 +381,34 @@ vows.describe('winton/logger').addBatch({ } }).addBatch({ "Building a logger with two file transports": { - topic: function() { new (winston.Logger)({ + topic: new (winston.Logger)({ transports: [ - new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog-info.log' ), level: 'info'}), - new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog-error.log' ), level: 'error'}) + new (winston.transports.File)({ + name: 'filelog-info.log', + filename: path.join(__dirname, 'fixtures', 'logs', 'filelog-info.log'), + level: 'info' + }), + new (winston.transports.File)({ + name: 'filelog-error.log', + filename: path.join(__dirname, 'fixtures', 'logs', 'filelog-error.log'), + level: 'error' + }) ] - })}, - "should not throw an exception": function (f) { - assert.doesNotThrow(f, Error) + }), + "should respond with a proper logger": function (logger) { + assert.include(logger._names, 'filelog-info.log'); + assert.include(logger._names, 'filelog-error.log'); + assert.lengthOf(logger.transports, 2); }, + "when one is removed": { + topic: function (logger) { + logger.remove('filelog-error.log'); + return logger; + }, + "should only have one transport": function (logger) { + assert.include(logger._names, 'filelog-info.log'); + assert.lengthOf(logger.transports, 1); + } + } } }).export(module);