Comparing version 0.9.0 to 1.0.0
@@ -1,3 +0,22 @@ | ||
v0.9.0 / 2015-02-03 | ||
======================== | ||
## v1.0.0 / 2015-04-07 | ||
### Breaking Changes | ||
* [#587](https://github.com/winstonjs/winston/pull/587) Do not extend `String` prototypes as a side effect of using `colors`. (`kenperkins`) | ||
* [#581](https://github.com/winstonjs/winston/pull/581) File transports now emit `error` on error of the underlying streams after `maxRetries` attempts. (`ambbell`). | ||
* [#583](https://github.com/winstonjs/winston/pull/583), [92729a](https://github.com/winstonjs/winston/commit/92729a68d71d07715501c35d94d2ac06ac03ca08) Use `os.EOL` for all file writing by default. (`Mik13`, `indexzero`) | ||
* [#532](https://github.com/winstonjs/winston/pull/532) Delete logger instance from `Container` when `close` event is emitted. (`snater`) | ||
* [#380](https://github.com/winstonjs/winston/pull/380) Rename `duration` to `durationMs`, which is now a number a not a string ending in `ms`. (`neoziro`) | ||
* [#253](https://github.com/winstonjs/winston/pull/253) Do not set a default level. When `level` is falsey on any `Transport` instance, any `Logger` instance uses the configured level (instead of the Transport level) (`jstamerj`). | ||
### Other changes | ||
* [b83de62](https://github.com/winstonjs/winston/commit/b83de62) Fix rendering of stack traces. | ||
* [c899cc](https://github.com/winstonjs/winston/commit/c899cc1f0719e49b26ec933e0fa263578168ea3b) Update documentation (Fixes [#549](https://github.com/winstonjs/winston/issues/549)) | ||
* [#551](https://github.com/winstonjs/winston/pull/551) Filter metadata along with messages | ||
* [#578](https://github.com/winstonjs/winston/pull/578) Fixes minor issue with `maxFiles` in `File` transport (Fixes [#556](https://github.com/winstonjs/winston/issues/556)). | ||
* [#560](https://github.com/winstonjs/winston/pull/560) Added `showLevel` support to `File` transport. | ||
* [#558](https://github.com/winstonjs/winston/pull/558) Added `showLevel` support to `Console` transport. | ||
## v0.9.0 / 2015-02-03 | ||
* [#496](https://github.com/flatiron/winston/pull/496) Updated default option handling for CLI (`oojacoboo`). | ||
@@ -4,0 +23,0 @@ * [f37634b](https://github.com/flatiron/winston/commit/f37634b) [dist] Only support `node >= 0.8.0`. (`indexzero`) |
@@ -26,2 +26,5 @@ # Winston Transports | ||
* [Graylog2](#graylog2-transport) | ||
* [Cassandra](#cassandra-transport) | ||
* [Azure Table](#azure-table) | ||
* [Airbrake](#airbrake-transport) | ||
@@ -54,2 +57,3 @@ ## Winston Core | ||
* __depth__ Numeric indicating how many times to recurse while formatting the object with `util.inspect` (only used with `prettyPrint: true`) (default null, unlimited) | ||
* __humanReadableUnhandledException__ Boolean flag indicating if uncaught exception should be output as human readable, instead of a single line | ||
@@ -290,7 +294,9 @@ *Metadata:* Logged via util.inspect(meta); | ||
The [winston-sns][18] transport uses amazon SNS to send emails, texts, or a bunch of other notifications. | ||
The [winston-sns][18] transport uses amazon SNS to send emails, texts, or a bunch of other notifications. Since this transport uses the Amazon AWS SDK for JavaScript, you can take advantage of the various methods of authentication found in Amazon's [Configuring the SDK in Node.js](http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html) document. | ||
``` js | ||
require('winston-sns').SNS; | ||
winston.add(winston.transports.SNS, options); | ||
var winston = require('winston'), | ||
winstonSNS = require('winston-sns'); | ||
winston.add(winstonSNS, options); | ||
``` | ||
@@ -300,10 +306,12 @@ | ||
* __aws_key:__ Your Amazon Web Services Key. *[required]* | ||
* __aws_secret:__ Your Amazon Web Services Secret. *[required]* | ||
* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]* | ||
* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]* | ||
* __aws_key:__ Your Amazon Web Services Key. | ||
* __aws_secret:__ Your Amazon Web Services Secret. | ||
* __region:__ AWS Region to use. Can be one of: `us-east-1`,`us-west-1`,`eu-west-1`,`ap-southeast-1`,`ap-northeast-1`,`us-gov-west-1`,`sa-east-1`. (default: `us-east-1`) | ||
* __subject:__ Subject for notifications. (default: "Winston Error Report") | ||
* __subject:__ Subject for notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Winston Error Report") | ||
* __message:__ Message of notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Level '%l' Error:\n%e\n\nMetadata:\n%m") | ||
* __level:__ lowest level this transport will log. (default: `info`) | ||
* __json:__ use json instead of a prettier (human friendly) string for meta information in the notification. (default: `false`) | ||
* __handleExceptions:__ set to true to have this transport handle exceptions. (default: `false`) | ||
@@ -356,3 +364,43 @@ ### Graylog2 Transport | ||
### Azure Table | ||
[winston-azuretable][21] is a Azure Table transport: | ||
``` js | ||
var azureLogger = require('winston-azuretable').AzureLogger | ||
winston.add(azureLogger, options); | ||
``` | ||
The Azure Table transport connects to an Azure Storage Account using the following options: | ||
* __useDevStorage__: Boolean flag denoting whether to use the Azure Storage Emulator (default: `false`) | ||
* __account__: Azure Storage Account Name. In lieu of this setting, you can set the environment variable: `AZURE_STORAGE_ACCOUNT` | ||
* __key__: Azure Storage Account Key. In lieu of this setting, you can set the environment variable: `AZURE_STORAGE_ACCESS_KEY` | ||
* __level__: lowest logging level transport to be logged (default: `info`) | ||
* __tableName__: name of the table to log messages (default: `log`) | ||
* __partitionKey__: table partition key to use (default: `process.env.NODE_ENV`) | ||
* __silent__: Boolean flag indicating whether to suppress output (default: `false`) | ||
### Airbrake Transport | ||
[winston-airbrake2][22] is a transport for winston that sends your logs to Airbrake.io. | ||
``` js | ||
var winston = require('winston'); | ||
winston.add(require('winston-airbrake2').Airbrake, options); | ||
``` | ||
The Airbrake transport utilises the node-airbrake module to send logs to the Airbrake.io API. You can set the following options: | ||
* __apiKey__: The project API Key. (required, default: null) | ||
* __name__: Transport name. (optional, default: 'airbrake') | ||
* __level__: The level of message that will be sent to Airbrake (optional, default: 'error') | ||
* __host__: The information that is displayed within the URL of the Airbrake interface. (optional, default: 'http://' + os.hostname()) | ||
* __env__: The environment will dictate what happens with your message. If your environment is currently one of the 'developmentEnvironments', the error will not be sent to Airbrake. (optional, default: process.env.NODE_ENV) | ||
* __timeout__: The maximum time allowed to send to Airbrake in milliseconds. (optional, default: 30000) | ||
* __developmentEnvironments__: The environments that will **not** send errors to Airbrake. (optional, default: ['development', 'test']) | ||
* __projectRoot__: Extra string sent to Airbrake. (optional, default: null) | ||
* __appVersion__: Extra string or number sent to Airbrake. (optional, default: null) | ||
* __consoleLogError__: Toggle the logging of errors to console when the current environment is in the developmentEnvironments array. (optional, default: false) | ||
## Find more Transports | ||
@@ -412,1 +460,3 @@ | ||
[20]: https://github.com/jorgebay/winston-cassandra | ||
[21]: https://github.com/jpoon/winston-azuretable | ||
[22]: https://github.com/rickcraig/winston-airbrake2 |
@@ -79,3 +79,3 @@ /* | ||
// | ||
// We only need to clone refrence types (Object) | ||
// We only need to clone reference types (Object) | ||
// | ||
@@ -243,5 +243,3 @@ if (obj instanceof Error) { | ||
output += ' ' + exports.serialize(meta); | ||
output += '\n' + stack.map(function (s) { | ||
return s + '\n'; | ||
}); | ||
output += '\n' + stack.join('\n'); | ||
} else { | ||
@@ -248,0 +246,0 @@ output += ' ' + exports.serialize(meta); |
@@ -9,3 +9,3 @@ /* | ||
var colors = require('colors'); | ||
var colors = require('colors/safe'); | ||
@@ -25,3 +25,3 @@ var config = exports, | ||
for (var i = 0, l = allColors[level].length; i < l; ++i) { | ||
colorized = colorized[allColors[level][i]]; | ||
colorized = colors[allColors[level][i]](colorized); | ||
} | ||
@@ -31,7 +31,7 @@ } else if (allColors[level].match(/\s/)) { | ||
for (var i = 0; i < colorArr.length; ++i) { | ||
colorized = colorized[colorArr[i]]; | ||
colorized = colors[colorArr[i]](colorized); | ||
} | ||
allColors[level] = colorArr; | ||
} else { | ||
colorized = colorized[allColors[level]]; | ||
colorized = colors[allColors[level]](colorized); | ||
} | ||
@@ -38,0 +38,0 @@ return colorized; |
@@ -40,3 +40,5 @@ /* | ||
Container.prototype.get = Container.prototype.add = function (id, options) { | ||
var existing; | ||
var self = this, | ||
existing; | ||
if (!this.loggers[id]) { | ||
@@ -76,2 +78,6 @@ // | ||
this.loggers[id] = new winston.Logger(options); | ||
this.loggers[id].on('close', function () { | ||
self._delete(id); | ||
}); | ||
} | ||
@@ -107,3 +113,3 @@ | ||
self.loggers[id].close(); | ||
delete self.loggers[id]; | ||
self._delete(id); | ||
} | ||
@@ -116,1 +122,10 @@ | ||
// | ||
// ### @private function _delete (id) | ||
// #### @id {string} Id of the Logger instance to delete from container | ||
// Deletes a `Logger` instance with the specified `id`. | ||
// | ||
Container.prototype._delete = function (id) { | ||
delete this.loggers[id]; | ||
} | ||
@@ -158,3 +158,9 @@ /* | ||
this.filters.forEach(function(filter) { | ||
msg = filter(msg); | ||
var filtered = filter(msg, meta, level); | ||
if (typeof filtered === 'string') | ||
msg = filtered; | ||
else { | ||
msg = filtered.msg; | ||
meta = filtered.meta; | ||
} | ||
}); | ||
@@ -372,2 +378,4 @@ | ||
}); | ||
this.emit('close'); | ||
}; | ||
@@ -484,4 +492,7 @@ | ||
// ### function addFilter (filter) | ||
// #### @filter {function} Filter function, called with the message as single | ||
// argument, expected to return the filtered message. | ||
// #### @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 | ||
// | ||
@@ -539,3 +550,3 @@ Logger.prototype.addFilter = function (filter) { | ||
meta.duration = (Date.now()) - this.start + 'ms'; | ||
meta.durationMs = (Date.now()) - this.start; | ||
@@ -575,3 +586,3 @@ return this.logger.info(msg, meta, callback); | ||
// Set the duration property of the metadata | ||
meta.duration = now - then + 'ms'; | ||
meta.durationMs = now - then; | ||
return this.info(msg, meta, callback); | ||
@@ -578,0 +589,0 @@ } |
@@ -11,3 +11,2 @@ /* | ||
util = require('util'), | ||
colors = require('colors'), | ||
common = require('../common'), | ||
@@ -77,2 +76,3 @@ Transport = require('./transport').Transport; | ||
timestamp: this.timestamp, | ||
showLevel: this.showLevel, | ||
prettyPrint: this.prettyPrint, | ||
@@ -79,0 +79,0 @@ raw: this.raw, |
@@ -13,6 +13,6 @@ /* | ||
util = require('util'), | ||
colors = require('colors'), | ||
common = require('../common'), | ||
Transport = require('./transport').Transport, | ||
Stream = require('stream').Stream; | ||
Stream = require('stream').Stream, | ||
os = require('os'); | ||
@@ -57,2 +57,5 @@ // | ||
this._stream = options.stream; | ||
this._stream.on('error', function(error){ | ||
self.emit('error', error); | ||
}); | ||
@@ -80,2 +83,4 @@ // | ||
this.depth = options.depth || null; | ||
this.eol = options.eol || os.EOL; | ||
this.maxRetries = options.maxRetries || 2; | ||
@@ -95,2 +100,3 @@ if (this.json) { | ||
this._draining = false; | ||
this._failures = 0; | ||
@@ -154,2 +160,11 @@ var now = new Date(); | ||
// | ||
// If failures exceeds maxRetries then we can't access the | ||
// stream. In this case we need to perform a noop and return | ||
// an error. | ||
// | ||
if (this._failures >= this.maxRetries) { | ||
return callback(new Error('Transport is in a failed state.')); | ||
} | ||
var self = this; | ||
@@ -171,3 +186,3 @@ | ||
humanReadableUnhandledException: this.humanReadableUnhandledException | ||
}) + '\n'; | ||
}) + this.eol; | ||
@@ -472,2 +487,11 @@ this._size += output.length; | ||
self._stream = fs.createWriteStream(fullname, self.options); | ||
self._stream.on('error', function(error){ | ||
if (self._failures < self.maxRetries) { | ||
self._createStream(); | ||
self._failures++; | ||
} | ||
else { | ||
self.emit('error', error); | ||
} | ||
}); | ||
@@ -474,0 +498,0 @@ // |
@@ -14,7 +14,7 @@ /* | ||
async = require('async'), | ||
colors = require('colors'), | ||
common = require('../common'), | ||
Transport = require('./transport').Transport, | ||
isWritable = require('isstream').isWritable, | ||
Stream = require('stream').Stream; | ||
Stream = require('stream').Stream, | ||
os = require('os'); | ||
@@ -60,2 +60,5 @@ // | ||
this._isStreams2 = isWritable(this._stream); | ||
this._stream.on('error', function(error){ | ||
self.emit('error', error); | ||
}); | ||
// | ||
@@ -81,6 +84,7 @@ // We need to listen for drain events when | ||
this.timestamp = options.timestamp != null ? options.timestamp : true; | ||
this.eol = options.eol || '\n'; | ||
this.eol = options.eol || os.EOL; | ||
this.tailable = options.tailable || false; | ||
this.depth = options.depth || null; | ||
this.showLevel = options.showLevel === undefined ? true : options.showLevel; | ||
this.maxRetries = options.maxRetries || 2; | ||
@@ -101,2 +105,3 @@ if (this.json) { | ||
this._opening = false; | ||
this._failures = 0; | ||
}; | ||
@@ -127,2 +132,11 @@ | ||
// | ||
// If failures exceeds maxRetries then we can't access the | ||
// stream. In this case we need to perform a noop and return | ||
// an error. | ||
// | ||
if (this._failures >= this.maxRetries) { | ||
return callback(new Error('Transport is in a failed state.')); | ||
} | ||
var self = this; | ||
@@ -143,2 +157,3 @@ | ||
timestamp: this.timestamp, | ||
showLevel: this.showLevel, | ||
stringify: this.stringify, | ||
@@ -460,2 +475,11 @@ label: this.label, | ||
self._isStreams2 = isWritable(self._stream); | ||
self._stream.on('error', function(error){ | ||
if (self._failures < self.maxRetries) { | ||
self._createStream(); | ||
self._failures++; | ||
} | ||
else { | ||
self.emit('error', error); | ||
} | ||
}); | ||
// | ||
@@ -564,3 +588,3 @@ // We need to listen for drain events when | ||
oldest = this._created - this.maxFiles; | ||
target = path.join(this.dirname, basename + (oldest === 0 ? oldest : '') + ext); | ||
target = path.join(this.dirname, basename + (oldest !== 0 ? oldest : '') + ext); | ||
fs.unlink(target, callback); | ||
@@ -567,0 +591,0 @@ }; |
var events = require('events'), | ||
util = require('util'), | ||
colors = require('colors'), | ||
common = require('../common'), | ||
@@ -5,0 +4,0 @@ Transport = require('./transport').Transport; |
@@ -22,3 +22,2 @@ /* | ||
options = options || {}; | ||
this.level = options.level === undefined ? 'info' : options.level; | ||
this.silent = options.silent || false; | ||
@@ -29,2 +28,9 @@ this.raw = options.raw || false; | ||
// | ||
// Do not set a default level. When `level` is falsey on any | ||
// `Transport` instance, any `Logger` instance uses the | ||
// configured level (instead of the Transport level) | ||
// | ||
this.level = options.level; | ||
this.handleExceptions = options.handleExceptions || false; | ||
@@ -31,0 +37,0 @@ this.exceptionsLevel = options.exceptionsLevel || 'error'; |
{ | ||
"name": "winston", | ||
"description": "A multi-transport async logging library for Node.js", | ||
"version": "0.9.0", | ||
"version": "1.0.0", | ||
"author": "Nodejitsu Inc. <info@nodejitsu.com>", | ||
@@ -11,3 +11,3 @@ "maintainers": [ | ||
"type": "git", | ||
"url": "https://github.com/flatiron/winston.git" | ||
"url": "https://github.com/winstonjs/winston.git" | ||
}, | ||
@@ -43,5 +43,5 @@ "keywords": [ | ||
"type": "MIT", | ||
"url": "https://raw.github.com/flatiron/winston/master/LICENSE" | ||
"url": "https://raw.github.com/winstonjs/winston/master/LICENSE" | ||
} | ||
] | ||
} |
@@ -1,2 +0,2 @@ | ||
# winston [![Build Status](https://secure.travis-ci.org/flatiron/winston.svg?branch=master)](http://travis-ci.org/flatiron/winston) | ||
# winston [![Build Status](https://secure.travis-ci.org/winstonjs/winston.svg?branch=master)](http://travis-ci.org/winstonjs/winston) | ||
@@ -24,3 +24,3 @@ A multi-transport async logging library for node.js. <span style="font-size:28px; font-weight:bold;">"CHILL WINSTON! ... I put it in the logs."</span> | ||
* [String interpolation](#string-interpolation) | ||
* [Transports](https://github.com/flatiron/winston/blob/master/docs/transports.md) | ||
* [Transports](https://github.com/winstonjs/winston/blob/master/docs/transports.md) | ||
* [Multiple transports of the same type](#multiple-transports-of-the-same-type) | ||
@@ -58,2 +58,5 @@ * [Profiling](#profiling) | ||
winston.info('Hello again distributed logs'); | ||
winston.level = 'debug'; | ||
winston.log('debug', 'Now my debug messages are written to console!'); | ||
``` | ||
@@ -140,3 +143,3 @@ | ||
``` | ||
``` js | ||
// Notice it was first in the Array above | ||
@@ -298,3 +301,3 @@ var infoFile = logger.transports[0]; | ||
``` | ||
``` js | ||
var logger = new winston.Logger({ | ||
@@ -483,3 +486,3 @@ transports: [ | ||
level: 'silly', | ||
colorize: 'true', | ||
colorize: true, | ||
label: 'category one' | ||
@@ -525,3 +528,3 @@ }, | ||
level: 'silly', | ||
colorize: 'true' | ||
colorize: true | ||
}, | ||
@@ -676,2 +679,3 @@ file: { | ||
* __formatter:__ If function is specified, its return value will be used instead of default output. (default undefined) | ||
* __debugStdout:__ Boolean flag indicating if 'debug'-level output should be redirected to stdout instead of to stderr. (default false) | ||
@@ -700,4 +704,5 @@ *Metadata:* Logged via util.inspect(meta); | ||
* __showLevel:__ Boolean flag indicating if we should prepend output with level (default true). | ||
* __formatter:__ If function is specified, its return value will be used instead of default output. (default undefined) | ||
* __formatter:__ If function is specified and `json` is set to `false`, its return value will be used instead of default output. (default undefined) | ||
* __tailable:__ If true, log files will be rolled based on maxsize and maxfiles, but in ascending order. The __filename__ will always have the most recent log lines. The larger the appended number, the older the log file. | ||
* __maxRetries:__ The number of stream creation retry attempts before entering a failed state. In a failed state the transport stays active but performs a NOOP on it's log function. (default 2) | ||
@@ -781,3 +786,2 @@ *Metadata:* Logged via util.inspect(meta); | ||
*Metadata:* Logged as a native JSON object. | ||
>>>>>>> 3b57730... Custom log formatter functionality were added. | ||
@@ -830,7 +834,9 @@ ### SimpleDB Transport | ||
The [winston-sns][21] transport uses amazon SNS to send emails, texts, or a bunch of other notifications. | ||
The [winston-sns][18] transport uses amazon SNS to send emails, texts, or a bunch of other notifications. Since this transport uses the Amazon AWS SDK for JavaScript, you can take advantage of the various methods of authentication found in Amazon's [Configuring the SDK in Node.js](http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html) document. | ||
``` js | ||
require('winston-sns').SNS; | ||
winston.add(winston.transports.SNS, options); | ||
var winston = require('winston'), | ||
winstonSNS = require('winston-sns'); | ||
winston.add(winstonSNS, options); | ||
``` | ||
@@ -840,10 +846,12 @@ | ||
* __aws_key:__ Your Amazon Web Services Key. *[required]* | ||
* __aws_secret:__ Your Amazon Web Services Secret. *[required]* | ||
* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]* | ||
* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]* | ||
* __aws_key:__ Your Amazon Web Services Key. | ||
* __aws_secret:__ Your Amazon Web Services Secret. | ||
* __region:__ AWS Region to use. Can be one of: `us-east-1`,`us-west-1`,`eu-west-1`,`ap-southeast-1`,`ap-northeast-1`,`us-gov-west-1`,`sa-east-1`. (default: `us-east-1`) | ||
* __subject:__ Subject for notifications. (default: "Winston Error Report") | ||
* __subject:__ Subject for notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Winston Error Report") | ||
* __message:__ Message of notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Level '%l' Error:\n%e\n\nMetadata:\n%m") | ||
* __level:__ lowest level this transport will log. (default: `info`) | ||
* __json:__ use json instead of a prettier (human friendly) string for meta information in the notification. (default: `false`) | ||
* __handleExceptions:__ set to true to have this transport handle exceptions. (default: `false`) | ||
@@ -907,6 +915,6 @@ ### Graylog2 Transport | ||
In addition to the options accepted by the [Node.js Cassandra driver](https://github.com/jorgebay/node-cassandra-cql) Client. | ||
In addition to the options accepted by the [Node.js Cassandra driver](https://github.com/datastax/nodejs-driver) Client. | ||
* __hosts:__ Cluster nodes that will handle the write requests: | ||
Array of strings containing the hosts, for example `['host1', 'host2']` (required). | ||
* __contactPoints:__ Cluster nodes that will handle the write requests: | ||
Array of strings containing the contact points, for example `['host1', 'host2']` (required). | ||
* __keyspace:__ The name of the keyspace that will contain the logs table (required). The keyspace should be already created in the cluster. | ||
@@ -921,3 +929,3 @@ | ||
var CustomLogger = winston.transports.CustomerLogger = function (options) { | ||
var CustomLogger = winston.transports.CustomLogger = function (options) { | ||
// | ||
@@ -924,0 +932,0 @@ // Name this logger |
@@ -130,5 +130,27 @@ /* | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
helpers.assertFailedTransport = function (transport) { | ||
return { | ||
topic: function () { | ||
var self = this; | ||
transport.on('error', function(emitErr){ | ||
transport.log('error', 'test message 2', {}, function(logErr, logged){ | ||
self.callback(emitErr, logErr); | ||
}); | ||
}); | ||
transport.log('error', 'test message'); | ||
}, | ||
"should emit an error": function (emitErr, logErr) { | ||
assert.instanceOf(emitErr, Error); | ||
assert.equal(emitErr.code, 'ENOENT'); | ||
}, | ||
"should enter noop failed state": function (emitErr, logErr) { | ||
assert.instanceOf(logErr, Error); | ||
assert.equal(transport._failures, transport.maxRetries); | ||
} | ||
}; | ||
}; | ||
helpers.testNpmLevels = function (transport, assertMsg, assertFn) { | ||
@@ -135,0 +157,0 @@ return helpers.testLevels(winston.config.npm.levels, transport, assertMsg, assertFn); |
@@ -24,2 +24,23 @@ /* log-filter-test.js: Test filtering of message content in winston. | ||
function maskSecrets(msg, meta) { | ||
var match; | ||
while (match = msg.match(/(secret|SECRET|Secret)/)) { | ||
var toBeMasked = match[1]; | ||
msg = msg.replace(toBeMasked, '******'); | ||
} | ||
meta = Object.keys(meta).reduce(function (maskedMeta, key) { | ||
if (key !== 'SECRET' && key !== 'Secret' && key !== 'secret') { | ||
maskedMeta[key] = meta[key]; | ||
} else { | ||
maskedMeta[key] = '<REDACTED>'; | ||
} | ||
return maskedMeta; | ||
}, {}); | ||
return { | ||
msg: msg, | ||
meta: meta | ||
}; | ||
} | ||
vows.describe('winston/logger/filter').addBatch({ | ||
@@ -30,3 +51,3 @@ "An instance of winston.Logger": { | ||
]}), | ||
"the addFilter() method": { | ||
"the addFilter() method, adding a filter only for the message": { | ||
topic: function (logger) { | ||
@@ -38,6 +59,6 @@ logger.addFilter(function (msg) { | ||
}, | ||
"should add the filter": function(logger) { | ||
"should add the filter": function (logger) { | ||
assert.equal(helpers.size(logger.filters), 1); | ||
}, | ||
"the log() method": { | ||
"the log() method with a filtered message": { | ||
topic: function (logger) { | ||
@@ -51,5 +72,38 @@ logger.once('logging', this.callback); | ||
} | ||
}, | ||
} | ||
}).addBatch({ | ||
"A fresh instance of winston.Logger": { | ||
topic: new (winston.Logger)({transports: [ | ||
new (winston.transports.Console)({ level: 'info' }) | ||
]}), | ||
"the addFilter() method adding a filter for the message and metadata": { | ||
topic: function (logger) { | ||
logger.addFilter(function (msg, meta) { | ||
return maskSecrets(msg, meta); | ||
}); | ||
return logger; | ||
}, | ||
"the log() method with a filtered message and filtered metadata": { | ||
topic: function (logger) { | ||
logger.once('logging', this.callback); | ||
logger.log('info', | ||
'We should make sure the secret stays SECRET.', | ||
{ 'SECRET': "You shouldn't see this.", | ||
'public': 'But you can look at this.', | ||
'secret': "We'll have to take you to Area-51 now.", | ||
'not-secret': 'No worries about this one.', | ||
'Secret': "It's confidential!" }); | ||
}, | ||
"should filter out secrets": function (transport, level, msg, meta) { | ||
assert.equal(msg, 'We should make sure the ****** stays ******.'); | ||
assert.equal(meta.SECRET, '<REDACTED>'); | ||
assert.equal(meta.public, 'But you can look at this.'); | ||
assert.equal(meta.secret, '<REDACTED>'); | ||
assert.equal(meta['not-secret'], 'No worries about this one.'); | ||
assert.equal(meta.Secret, '<REDACTED>'); | ||
} | ||
} | ||
} | ||
} | ||
}).export(module); | ||
@@ -114,3 +114,2 @@ /* | ||
assert.equal(level, 'info'); | ||
assert.match(meta.duration, /(\d+)ms/); | ||
assert.isTrue(typeof logger.profilers['test'] === 'undefined'); | ||
@@ -134,3 +133,2 @@ }, | ||
assert.equal(level, 'info'); | ||
assert.match(meta.duration, /(\d+)ms/); | ||
assert.equal(meta.some, 'data'); | ||
@@ -152,3 +150,2 @@ }, | ||
assert.equal(level, 'info'); | ||
assert.match(meta.duration, /(\d+)ms/); | ||
} | ||
@@ -173,3 +170,2 @@ } | ||
assert.equal(level, 'info'); | ||
assert.match(meta.duration, /(\d+)ms/); | ||
} | ||
@@ -189,7 +185,5 @@ }, | ||
assert.equal(level, 'info'); | ||
assert.match(meta.duration, /(\d+)ms/); | ||
var duration = parseInt(meta.duration); | ||
assert.isNumber(duration); | ||
assert.isTrue(duration >= 50 && duration < 100); | ||
assert.isNumber(meta.durationMs); | ||
assert.isTrue(meta.durationMs >= 50 && meta.durationMs < 100); | ||
} | ||
@@ -196,0 +190,0 @@ } |
@@ -13,3 +13,4 @@ /* | ||
winston = require('../../lib/winston'), | ||
helpers = require('../helpers'); | ||
helpers = require('../helpers'), | ||
stdMocks = require('std-mocks'); | ||
@@ -21,2 +22,30 @@ var npmTransport = new (winston.transports.Console)(), | ||
"An instance of the Console Transport": { | ||
"with showLevel on": { | ||
topic : function() { | ||
npmTransport.showLevel = true; | ||
stdMocks.use(); | ||
npmTransport.log('info', ''); | ||
}, | ||
"should have level prepended": function () { | ||
stdMocks.restore(); | ||
var output = stdMocks.flush(), | ||
line = output.stdout[0]; | ||
assert.equal(line, 'info: \n'); | ||
} | ||
}, | ||
"with showLevel off": { | ||
topic : function() { | ||
npmTransport.showLevel = false; | ||
stdMocks.use(); | ||
npmTransport.log('info', ''); | ||
}, | ||
"should not have level prepended": function () { | ||
stdMocks.restore(); | ||
var output = stdMocks.flush(), | ||
line = output.stdout[0]; | ||
assert.equal(line, undefined); | ||
} | ||
}, | ||
"with npm levels": { | ||
@@ -23,0 +52,0 @@ "should have the proper methods defined": function () { |
@@ -25,2 +25,5 @@ /* | ||
}), | ||
failedDailyRotateFileTransport = new (winston.transports.DailyRotateFile)({ | ||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'dir404', 'testfile.log') | ||
}), | ||
streamTransport = new (winston.transports.DailyRotateFile)({ stream: stream }); | ||
@@ -39,2 +42,10 @@ | ||
}, | ||
"when passed an invalid filename": { | ||
"should have proper methods defined": function () { | ||
helpers.assertDailyRotateFile(failedDailyRotateFileTransport); | ||
}, | ||
"should enter noop failed state": function () { | ||
helpers.assertFailedTransport(failedDailyRotateFileTransport); | ||
} | ||
}, | ||
"when passed a valid file stream": { | ||
@@ -41,0 +52,0 @@ "should have the proper methods defined": function () { |
@@ -26,3 +26,3 @@ /* | ||
}); | ||
vows.describe('winston/transports/file/maxfiles').addBatch({ | ||
@@ -47,11 +47,11 @@ "An instance of the File Transport": { | ||
created = 0; | ||
function data(ch) { | ||
return new Array(1018).join(String.fromCharCode(65 + ch)); | ||
}; | ||
function logKbytes(kbytes, txt) { | ||
// | ||
// With no timestamp and at the info level, | ||
// winston adds exactly 7 characters: | ||
// winston adds exactly 7 characters: | ||
// [info](4)[ :](2)[\n](1) | ||
@@ -63,3 +63,3 @@ // | ||
} | ||
maxfilesTransport.on('logged', function () { | ||
@@ -69,6 +69,6 @@ if (++created === 6) { | ||
} | ||
logKbytes(4, created); | ||
}); | ||
logKbytes(4, created); | ||
@@ -80,14 +80,14 @@ }, | ||
fullpath = path.join(__dirname, '..', 'fixtures', 'logs', file); | ||
// There should be no files with that name | ||
if (num >= 0 && num < 3) { | ||
return assert.throws(function () { | ||
fs.statSync(file); | ||
assert.throws(function () { | ||
fs.statSync(fullpath); | ||
}, Error); | ||
} | ||
// The other files should be exist | ||
assert.doesNotThrow(function () { | ||
fs.statSync(file); | ||
}, Error); | ||
} else { | ||
// The other files should be exist | ||
assert.doesNotThrow(function () { | ||
fs.statSync(fullpath); | ||
}, Error); | ||
} | ||
} | ||
@@ -107,2 +107,2 @@ }, | ||
} | ||
}).export(module); | ||
}).export(module); |
@@ -14,2 +14,3 @@ /* | ||
winston = require('../../lib/winston'), | ||
stdMocks = require('std-mocks'), | ||
helpers = require('../helpers'); | ||
@@ -25,2 +26,5 @@ | ||
}), | ||
failedFileTransport = new (winston.transports.File)({ | ||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'dir404', 'testfile.log') | ||
}), | ||
streamTransport = new (winston.transports.File)({ stream: stream }); | ||
@@ -39,2 +43,10 @@ | ||
}, | ||
"when passed an invalid filename": { | ||
"should have proper methods defined": function () { | ||
helpers.assertFile(failedFileTransport); | ||
}, | ||
"should enter noop failed state": function () { | ||
helpers.assertFailedTransport(failedFileTransport); | ||
} | ||
}, | ||
"when passed a valid file stream": { | ||
@@ -48,2 +60,28 @@ "should have the proper methods defined": function () { | ||
}) | ||
}, | ||
"streaming to stdout": { | ||
topic: function () { | ||
var transport = new (winston.transports.File)({ | ||
stream: process.stdout, timestamp: false, json: false | ||
}); | ||
stdMocks.use(); | ||
return transport; | ||
}, | ||
"with showLevel off": { | ||
topic: function (stdoutStreamTransport) { | ||
stdoutStreamTransport.showLevel = false; | ||
stdoutStreamTransport.log('info', '', undefined, this.callback); | ||
}, | ||
"should not have level prepended": function () { | ||
var output = stdMocks.flush(), | ||
line = output.stdout[0]; | ||
assert.equal(line, '\n'); | ||
} | ||
}, | ||
// there would be a "with showLevel on" here but I think it's a bug in | ||
// this version of vows. ugprading causes even more problems | ||
teardown: function() { | ||
stdMocks.restore(); | ||
} | ||
} | ||
@@ -50,0 +88,0 @@ } |
Sorry, the diff of this file is not supported yet
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
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
261851
71
5804
1
1020