Comparing version 1.1.2 to 2.0.0
@@ -0,1 +1,33 @@ | ||
## v2.0.0 / 2015-10-29 | ||
### OMG IT'S MY SISTER'S BIRTHDAY EDITION | ||
#### Breaking changes | ||
**Most important** | ||
- **[0f82204](https://github.com/winstonjs/winston/commit/0f82204) Move `winston.transports.DailyRotateFile` [into a separate module](https://github.com/winstonjs/winston-daily-rotate-file)**: `require('winston-daily-rotate-file');` | ||
- **[fb9eec0](https://github.com/winstonjs/winston/commit/fb9eec0) Reverse log levels in `npm` and `cli` configs to conform to [RFC524](https://tools.ietf.org/html/rfc5424). Fixes [#424](https://github.com/winstonjs/winston/pull/424) [#406](https://github.com/winstonjs/winston/pull/406) [#290](https://github.com/winstonjs/winston/pull/290)** | ||
- **[8cd8368](https://github.com/winstonjs/winston/commit/8cd8368) Change the method signature to a `filter` function to be consistent with `rewriter` and log functions:** | ||
``` js | ||
function filter (level, msg, meta, inst) { | ||
// Filter logic goes here... | ||
} | ||
``` | ||
**Other breaking changes** | ||
- [e0c9dde](https://github.com/winstonjs/winston/commit/e0c9dde) Remove `winston.transports.Webhook`. Use `winston.transports.Http` instead. | ||
- [f71e638](https://github.com/winstonjs/winston/commit/f71e638) Remove `Logger.prototype.addRewriter` and `Logger.prototype.addFilter` since they just push to an Array of functions. Use `logger.filters.push` or `logger.rewriters.push` explicitly instead. | ||
- [a470ab5](https://github.com/winstonjs/winston/commit/a470ab5) No longer respect the `handleExceptions` option to `new winston.Logger`. Instead just pass in the `exceptionHandlers` option itself. | ||
- [8cb7048](https://github.com/winstonjs/winston/commit/8cb7048) Removed `Logger.prototype.extend` functionality | ||
#### New features | ||
- [3aa990c](https://github.com/winstonjs/winston/commit/3aa990c) Added `Logger.prototype.configure` which now contains all logic previously in the `winston.Logger` constructor function. (`indexzero`) | ||
- [#726](https://github.com/winstonjs/winston/pull/726) Update .npmignore (`coreybutler`) | ||
- [#700](https://github.com/winstonjs/winston/pull/700) Add an `eol` option to the `Console` transport. (`aquavitae`) | ||
- [#731](https://github.com/winstonjs/winston/pull/731) Update `lib/transports.js` for better static analysis. (`indexzero`) | ||
#### Fixes, refactoring, and optimizations. OH MY! | ||
- [#632](https://github.com/winstonjs/winston/pull/632) Allow `File` transport to be an `objectMode` writable stream. (`stambata`) | ||
- [#527](https://github.com/winstonjs/winston/issues/527), [163f4f9](https://github.com/winstonjs/winston/commit/163f4f9), [3747ccf](https://github.com/winstonjs/winston/commit/3747ccf) Performance optimizations and string interpolation edge cases (`indexzero`) | ||
- [f0edafd](https://github.com/winstonjs/winston/commit/f0edafd) Code cleanup for reability, ad-hoc styleguide enforcement (`indexzero`) | ||
## v1.1.1 - v1.1.2 / 2015-10 | ||
@@ -2,0 +34,0 @@ ### MINOR FIXES EDITION |
@@ -26,3 +26,4 @@ /* | ||
} | ||
} else if (allColors[level].match(/\s/)) { | ||
} | ||
else if (allColors[level].match(/\s/)) { | ||
var colorArr = allColors[level].split(/\s+/); | ||
@@ -33,5 +34,7 @@ for (var i = 0; i < colorArr.length; ++i) { | ||
allColors[level] = colorArr; | ||
} else { | ||
} | ||
else { | ||
colorized = colors[allColors[level]](colorized); | ||
} | ||
return colorized; | ||
@@ -38,0 +41,0 @@ }; |
@@ -12,25 +12,25 @@ /* | ||
cliConfig.levels = { | ||
silly: 0, | ||
input: 1, | ||
verbose: 2, | ||
prompt: 3, | ||
debug: 4, | ||
info: 5, | ||
data: 6, | ||
help: 7, | ||
warn: 8, | ||
error: 9 | ||
error: 0, | ||
warn: 1, | ||
help: 2, | ||
data: 3, | ||
info: 4, | ||
debug: 5, | ||
prompt: 6, | ||
verbose: 7, | ||
input: 8, | ||
silly: 9, | ||
}; | ||
cliConfig.colors = { | ||
silly: 'magenta', | ||
error: 'red', | ||
warn: 'yellow', | ||
help: 'cyan', | ||
data: 'grey', | ||
info: 'green', | ||
debug: 'blue', | ||
prompt: 'grey', | ||
verbose: 'cyan', | ||
input: 'grey', | ||
verbose: 'cyan', | ||
prompt: 'grey', | ||
debug: 'blue', | ||
info: 'green', | ||
data: 'grey', | ||
help: 'cyan', | ||
warn: 'yellow', | ||
error: 'red' | ||
}; | ||
silly: 'magenta' | ||
}; |
@@ -12,17 +12,17 @@ /* | ||
npmConfig.levels = { | ||
silly: 0, | ||
debug: 1, | ||
verbose: 2, | ||
info: 3, | ||
warn: 4, | ||
error: 5 | ||
error: 0, | ||
warn: 1, | ||
info: 2, | ||
verbose: 3, | ||
debug: 4, | ||
silly: 5 | ||
}; | ||
npmConfig.colors = { | ||
silly: 'magenta', | ||
error: 'red', | ||
warn: 'yellow', | ||
info: 'green', | ||
verbose: 'cyan', | ||
debug: 'blue', | ||
info: 'green', | ||
warn: 'yellow', | ||
error: 'red' | ||
}; | ||
silly: 'magenta' | ||
}; |
@@ -19,3 +19,3 @@ /* | ||
info: 6, | ||
debug: 7, | ||
debug: 7 | ||
}; | ||
@@ -31,3 +31,3 @@ | ||
info: 'green', | ||
debug: 'blue', | ||
}; | ||
debug: 'blue' | ||
}; |
@@ -17,2 +17,4 @@ /* | ||
const formatRegExp = /%[sdj%]/g; | ||
// | ||
@@ -26,6 +28,37 @@ // ### function Logger (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); | ||
}); | ||
} | ||
@@ -52,64 +85,20 @@ // | ||
// | ||
// 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); | ||
['rewriters', 'filters'].forEach(function (kind) { | ||
self[kind] = Array.isArray(options[kind]) | ||
? options[kind] | ||
: []; | ||
}); | ||
if (transport.handleExceptions) { | ||
handleExceptions = true; | ||
} | ||
}); | ||
} | ||
if (options.rewriters) { | ||
options.rewriters.forEach(function (rewriter) { | ||
self.addRewriter(rewriter); | ||
}); | ||
} | ||
if (options.exceptionHandlers) { | ||
handleExceptions = true; | ||
options.exceptionHandlers.forEach(function (handler) { | ||
self._hnames.push(handler.name); | ||
self.exceptionHandlers[handler.name] = handler; | ||
}); | ||
this.handleExceptions(options.exceptionHandlers); | ||
} | ||
if (options.handleExceptions || handleExceptions) { | ||
this.handleExceptions(); | ||
} | ||
}; | ||
// | ||
// Inherit from `events.EventEmitter`. | ||
// | ||
util.inherits(Logger, events.EventEmitter); | ||
// | ||
// ### function extend (target) | ||
// #### @target {Object} Target to extend. | ||
// Extends the target object with a 'log' method | ||
// along with a method for each level in this instance. | ||
// | ||
Logger.prototype.extend = function (target) { | ||
var self = this; | ||
['log', 'profile', 'startTimer'].concat(Object.keys(this.levels)).forEach(function (method) { | ||
target[method] = function () { | ||
return self[method].apply(self, arguments); | ||
}; | ||
}); | ||
return this; | ||
}; | ||
// | ||
// ### function log (level, msg, [meta], callback) | ||
@@ -123,19 +112,24 @@ // #### @level {string} Level at which to log the message. | ||
Logger.prototype.log = function (level) { | ||
var self = this, | ||
args = Array.prototype.slice.call(arguments, 1); | ||
var args = Array.prototype.slice.call(arguments, 1), | ||
self = this, | ||
transports; | ||
while(args[args.length - 1] === null) { | ||
while (args[args.length - 1] === null) { | ||
args.pop(); | ||
} | ||
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null, | ||
meta = typeof args[args.length - 1] === 'object' && Object.prototype.toString.call(args[args.length - 1]) !== '[object RegExp]' ? args.pop() : {}, | ||
msg = util.format.apply(null, args); | ||
// | ||
// Determining what is `meta` and what are arguments for string interpolation | ||
// turns out to be VERY tricky. e.g. in the cases like this: | ||
// | ||
// logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' }); | ||
// | ||
var callback = typeof args[args.length - 1] === 'function' | ||
? args.pop() | ||
: null; | ||
// If we should pad for levels, do so | ||
if (this.padLevels) { | ||
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg; | ||
} | ||
function onError (err) { | ||
// | ||
// Handle errors appropriately. | ||
// | ||
function onError(err) { | ||
if (callback) { | ||
@@ -149,4 +143,3 @@ callback(err); | ||
if (Object.keys(this.transports).length === 0) { | ||
if (this._names.length === 0) { | ||
return onError(new Error('Cannot log with no transports.')); | ||
@@ -158,2 +151,53 @@ } | ||
// | ||
// If there are no transports that match the level | ||
// then be eager and return. This could potentially be calculated | ||
// during `setLevels` for more performance gains. | ||
// | ||
var targets = this._names.filter(function (name) { | ||
var transport = self.transports[name]; | ||
return (transport.level && self.levels[transport.level] >= self.levels[level]) | ||
|| (!transport.level && self.levels[self.level] >= self.levels[level]); | ||
}); | ||
if (!targets.length) { | ||
if (callback) { callback(); } | ||
return; | ||
} | ||
// | ||
// Determining what is `meta` and what are arguments for string interpolation | ||
// turns out to be VERY tricky. e.g. in the cases like this: | ||
// | ||
// logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' }); | ||
// | ||
var metaType = Object.prototype.toString.call(args[args.length - 1]), | ||
fmtMatch = args[0].match && args[0].match(formatRegExp), | ||
isFormat = fmtMatch && fmtMatch.length, | ||
validMeta = !isFormat | ||
? metaType === '[object Object]' || metaType === '[object Error]' || metaType === '[object Array]' | ||
: metaType === '[object Object]', | ||
meta = validMeta ? args.pop() : {}, | ||
msg = util.format.apply(null, args); | ||
// | ||
// Respond to the callback. | ||
// | ||
function finish(err) { | ||
if (callback) { | ||
if (err) return callback(err); | ||
callback(null, level, msg, meta); | ||
} | ||
callback = null; | ||
if (!err) { | ||
self.emit('logged', level, msg, meta); | ||
} | ||
} | ||
// If we should pad for levels, do so | ||
if (this.padLevels) { | ||
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg; | ||
} | ||
this.rewriters.forEach(function (rewriter) { | ||
@@ -164,3 +208,3 @@ meta = rewriter(level, msg, meta, self); | ||
this.filters.forEach(function(filter) { | ||
var filtered = filter(msg, meta, level, self); | ||
var filtered = filter(level, msg, meta, self); | ||
if (typeof filtered === 'string') | ||
@@ -189,36 +233,17 @@ msg = filtered; | ||
// | ||
function emit(name, next) { | ||
function transportLog(name, next) { | ||
var transport = self.transports[name]; | ||
if ((transport.level && self.levels[transport.level] <= self.levels[level]) | ||
|| (!transport.level && self.levels[self.level] <= self.levels[level])) { | ||
transport.log(level, msg, meta, function (err) { | ||
if (err) { | ||
err.transport = transport; | ||
cb(err); | ||
return next(); | ||
} | ||
self.emit('logging', transport, level, msg, meta); | ||
next(); | ||
}); | ||
} else { | ||
transport.log(level, msg, meta, function (err) { | ||
if (err) { | ||
err.transport = transport; | ||
finish(err); | ||
return next(); | ||
} | ||
self.emit('logging', transport, level, msg, meta); | ||
next(); | ||
} | ||
}); | ||
} | ||
// | ||
// Respond to the callback | ||
// | ||
function cb(err) { | ||
if (callback) { | ||
if (err) return callback(err); | ||
callback(null, level, msg, meta); | ||
} | ||
callback = null; | ||
if (!err) { | ||
self.emit('logged', level, msg, meta); | ||
} | ||
} | ||
async.forEach(this._names, emit, cb); | ||
async.forEach(targets, transportLog, finish); | ||
return this; | ||
@@ -268,3 +293,3 @@ }; | ||
// | ||
function addResults (transport, next) { | ||
function addResults(transport, next) { | ||
queryTransport(transport, function (err, result) { | ||
@@ -391,4 +416,5 @@ // | ||
// | ||
// ### function handleExceptions () | ||
// Handles `uncaughtException` events for the current process | ||
// ### function handleExceptions ([tr0, tr1...] || tr0, tr1, ...) | ||
// Handles `uncaughtException` events for the current process by | ||
// ADDING any handlers passed in. | ||
// | ||
@@ -409,2 +435,3 @@ Logger.prototype.handleExceptions = function () { | ||
this.exceptionHandlers = this.exceptionHandlers || {}; | ||
handlers.forEach(function (handler) { | ||
@@ -491,25 +518,2 @@ self.exceptionHandlers[handler.name] = handler; | ||
// | ||
// ### function addRewriter (transport, [options]) | ||
// #### @transport {Transport} Prototype of the Transport object to add. | ||
// #### @options {Object} **Optional** Options for the Transport to add. | ||
// #### @instance {Boolean} **Optional** Value indicating if `transport` is already instantiated. | ||
// Adds a transport of the specified type to this instance. | ||
// | ||
Logger.prototype.addRewriter = function (rewriter) { | ||
this.rewriters.push(rewriter); | ||
} | ||
// | ||
// ### function addFilter (filter) | ||
// #### @filter {function} Filter function, called with the message and | ||
// optional metadata as the two arguments. | ||
// Expected to return either the filtered message or an object with properties: | ||
// - msg = the filtered message string | ||
// - meta = the filtered metadata object | ||
// | ||
Logger.prototype.addFilter = function (filter) { | ||
this.filters.push(filter); | ||
} | ||
// | ||
// ### function clear () | ||
@@ -519,5 +523,5 @@ // 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); | ||
}; | ||
@@ -553,22 +557,15 @@ | ||
var ProfileHandler = function (logger) { | ||
this.logger = logger; | ||
this.start = Date.now(); | ||
this.done = function (msg) { | ||
var args, callback, meta; | ||
args = Array.prototype.slice.call(arguments); | ||
callback = typeof args[args.length - 1] === 'function' ? args.pop() : null; | ||
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {}; | ||
meta.durationMs = (Date.now()) - this.start; | ||
return this.logger.info(msg, meta, callback); | ||
} | ||
} | ||
// | ||
// ### function startTimer () | ||
// Returns an object corresponding to a specific timing. When done | ||
// is called the timer will finish and log the duration. e.g.: | ||
// | ||
// timer = winston.startTimer() | ||
// setTimeout(function(){ | ||
// timer.done("Logging message"); | ||
// }, 1000); | ||
// | ||
Logger.prototype.startTimer = function () { | ||
return new ProfileHandler(this); | ||
} | ||
}; | ||
@@ -716,1 +713,26 @@ // | ||
}; | ||
// | ||
// ### @private ProfileHandler | ||
// Constructor function for the ProfileHandler instance used by | ||
// `Logger.prototype.startTimer`. When done is called the timer | ||
// will finish and log the duration. | ||
// | ||
function ProfileHandler(logger) { | ||
this.logger = logger; | ||
this.start = Date.now(); | ||
} | ||
// | ||
// ### function done (msg) | ||
// Ends the current timer (i.e. ProfileHandler) instance and | ||
// logs the `msg` along with the duration since creation. | ||
// | ||
ProfileHandler.prototype.done = function (msg) { | ||
var args = Array.prototype.slice.call(arguments), | ||
callback = typeof args[args.length - 1] === 'function' ? args.pop() : null, | ||
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {}; | ||
meta.duration = (Date.now()) - this.start + 'ms'; | ||
return this.logger.info(msg, meta, callback); | ||
}; |
@@ -9,27 +9,22 @@ /* | ||
var fs = require('fs'), | ||
path = require('path'), | ||
common = require('./common'); | ||
var path = require('path'); | ||
var transports = exports; | ||
// | ||
// Setup all transports as lazy-loaded getters. | ||
// | ||
fs.readdirSync(path.join(__dirname, 'transports')).forEach(function (file) { | ||
var transport = file.replace('.js', ''), | ||
name = common.capitalize(transport); | ||
Object.defineProperties( | ||
exports, | ||
['Console', 'File', 'Http', 'Memory'] | ||
.reduce(function (acc, name) { | ||
acc[name] = { | ||
configurable: true, | ||
enumerable: true, | ||
get: function () { | ||
var fullpath = path.join(__dirname, 'transports', name.toLowerCase()); | ||
return exports[name] = require(fullpath)[name]; | ||
} | ||
}; | ||
if (transport === 'transport') { | ||
return; | ||
} | ||
else if (~transport.indexOf('-')) { | ||
name = transport.split('-').map(function (part) { | ||
return common.capitalize(part); | ||
}).join(''); | ||
} | ||
transports.__defineGetter__(name, function () { | ||
return require('./transports/' + transport)[name]; | ||
}); | ||
}); | ||
return acc; | ||
}, {}) | ||
); |
@@ -10,2 +10,3 @@ /* | ||
var events = require('events'), | ||
os = require('os'), | ||
util = require('util'), | ||
@@ -35,2 +36,3 @@ common = require('../common'), | ||
this.stderrLevels = setStderrLevels(options.stderrLevels, options.debugStdout); | ||
this.eol = options.eol || os.EOL; | ||
@@ -121,3 +123,3 @@ if (this.json) { | ||
} else { | ||
process.stdout.write(output + '\n'); | ||
process.stdout.write(output + this.eol); | ||
} | ||
@@ -124,0 +126,0 @@ |
@@ -162,4 +162,7 @@ /* | ||
humanReadableUnhandledException: this.humanReadableUnhandledException | ||
}) + this.eol; | ||
}); | ||
if (typeof output === 'string') { | ||
output += this.eol; | ||
} | ||
@@ -166,0 +169,0 @@ if (!this.filename) { |
{ | ||
"name": "winston", | ||
"description": "A multi-transport async logging library for Node.js", | ||
"version": "1.1.2", | ||
"version": "2.0.0", | ||
"author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
"maintainers": [ | ||
"indexzero <charlie@nodejitsu.com>" | ||
"Jarrett Cruger <jcrugzz@gmail.com>", | ||
"Alberto Pose <albertopose@gmail.com>" | ||
], | ||
@@ -14,2 +15,3 @@ "repository": { | ||
"keywords": [ | ||
"winston", | ||
"logging", | ||
@@ -16,0 +18,0 @@ "sysadmin", |
@@ -41,3 +41,2 @@ # winston [![Build Status](https://secure.travis-ci.org/winstonjs/winston.svg?branch=master)](http://travis-ci.org/winstonjs/winston) | ||
* [Using winston in a CLI tool](#using-winston-in-a-cli-tool) | ||
* [Extending another object with Logging](#extending-another-object-with-logging) | ||
* [Filters and Rewriters](#filters-and-rewriters) | ||
@@ -51,2 +50,4 @@ * [Adding Custom Transports](#adding-custom-transports) | ||
Logging levels in `winston` conform to the severity ordering specified by [RFC524](https://tools.ietf.org/html/rfc5424): _severity of all levels is assumed to be numerically **ascending** from most important to least important._ | ||
### Using the Default Logger | ||
@@ -99,6 +100,31 @@ The default logger is accessible through the winston module directly. Any method that you could call on an instance of a logger is available on the default logger: | ||
// | ||
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 | ||
@@ -333,2 +359,16 @@ In addition to logging string messages, winston will also optionally log additional JSON metadata objects. Adding metadata is simple: | ||
Each `level` is given a specific integer priority. The higher the priority the more important the message is considered to be, and the lower the corresponding integer priority. For example, `npm` logging levels are prioritized from 0 to 5 (highest to lowest): | ||
``` js | ||
{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 } | ||
``` | ||
Similarly, as specified exactly in RFC524 the `syslog` levels are prioritized from 0 to 7 (highest to lowest). | ||
```js | ||
{ emerg: 0, alert: 1, crit: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7 } | ||
``` | ||
If you do not explicitly define the levels that `winston` should use the `npm` levels above will be used. | ||
### Using Logging Levels | ||
@@ -358,3 +398,3 @@ Setting the level for your logging message can be accomplished in one of two ways. You can pass a string representing the logging level to the log() method or use the level specified methods defined on every winston Logger. | ||
Winston allows you to set a `level` on each transport that specifies the level of messages this transport should log. For example, you could log only errors to the console, with the full logs in a file (note that the default level of a transport is `info`): | ||
`winston` allows you to define a `level` property on each transport which specifies the **maximum** level of messages that a transport should log. For example, using the `npm` levels you could log only `error` messages to the console and everything `info` and below to a file (which includes `error` messages): | ||
@@ -365,3 +405,6 @@ ``` js | ||
new (winston.transports.Console)({ level: 'error' }), | ||
new (winston.transports.File)({ filename: 'somefile.log' }) | ||
new (winston.transports.File)({ | ||
filename: 'somefile.log', | ||
level: 'info' | ||
}) | ||
] | ||
@@ -629,21 +672,18 @@ }); | ||
### Extending another object with Logging | ||
Often in a given code base with lots of Loggers it is useful to add logging methods to a different object so that these methods can be called with less syntax. Winston exposes this functionality via the 'extend' method: | ||
### 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 myObject = {}; | ||
logger.extend(myObject); | ||
// | ||
// You can now call logger methods on 'myObject' | ||
// | ||
myObject.info("127.0.0.1 - there's no place like home"); | ||
var logger = new winston.Logger({ | ||
rewriters: [function (level, msg, meta) { /* etc etc */ }] | ||
filters: [function (level, msg, meta) { /* etc etc */ }] | ||
}) | ||
``` | ||
### 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. | ||
Like any Array they can also be modified at runtime with no adverse side-effects to the `winston` internals. | ||
``` js | ||
logger.addFilter(function(msg, meta, level) { | ||
logger.filters.push(function(level, msg, meta) { | ||
return meta.production | ||
@@ -666,3 +706,3 @@ ? maskCardNumbers(msg) | ||
``` js | ||
logger.addRewriter(function(level, msg, meta) { | ||
logger.rewriters.push(function(level, msg, meta) { | ||
if (meta.creditCard) { | ||
@@ -669,0 +709,0 @@ meta.creditCard = maskCardNumbers(meta.creditCard) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
830
3
2
123809
19
2608