Skip to content

Commit

Permalink
Custom log formatter functionality were added.
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyMelnik authored and indexzero committed Jan 27, 2015
1 parent 4c08191 commit a34f7d2
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 11 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ There are two different ways to use winston: directly via the default logger, or
* [Using winston in a CLI tool](#using-winston-in-a-cli-tool)
* [Extending another object with Logging](#extending-another-object-with-logging)
* [Working with transports](#working-with-transports)
* [Adding Custom Transports](#adding-custom-transports)
* [Adding Custom Transports](#adding-custom-transports)
* [Installation](#installation)
* [Run Tests](#run-tests)

Expand Down Expand Up @@ -645,6 +645,7 @@ The Console transport takes a few simple options:
* __prettyPrint:__ Boolean flag indicating if we should `util.inspect` the meta (default false). If function is specified, its return value will be the string representing the meta.
* __depth__ Numeric indicating how many times to recurse while formatting the object with `util.inspect` (only used with `prettyPrint: true`) (default null, unlimited)
* __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)

*Metadata:* Logged via util.inspect(meta);

Expand All @@ -668,6 +669,7 @@ The File transport should really be the 'Stream' transport since it will accept
* __depth__ Numeric indicating how many times to recurse while formatting the object with `util.inspect` (only used with `prettyPrint: true`) (default null, unlimited)
* __logstash:__ If true, messages will be logged as JSON and formatted for logstash (default false).
* __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)

*Metadata:* Logged via util.inspect(meta);

Expand Down Expand Up @@ -737,6 +739,17 @@ As of `0.3.0` the MongoDB transport has been broken out into a new module: [wins

For more information about its arguments, check [winston-mongodb's README][16].

* __level:__ Level of messages that this transport should log.
* __silent:__ Boolean flag indicating whether to suppress output.
* __db:__ The name of the database you want to log to. *[required]*
* __collection__: The name of the collection you want to store log messages in, defaults to 'log'.
* __safe:__ Boolean indicating if you want eventual consistency on your log messages, if set to true it requires an extra round trip to the server to ensure the write was committed, defaults to true.
* __host:__ The host running MongoDB, defaults to localhost.
* __port:__ The port on the host that MongoDB is running on, defaults to MongoDB's default port.

*Metadata:* Logged as a native JSON object.
>>>>>>> 3b57730... Custom log formatter functionality were added.

This comment has been minimized.

Copy link
@lookfirst

lookfirst Mar 30, 2015

Contributor

Bad merge line left in

This comment has been minimized.

Copy link
@indexzero

indexzero Mar 30, 2015

Member

Doh!

### SimpleDB Transport

The [winston-simpledb][18] transport is just as easy:
Expand Down Expand Up @@ -902,6 +915,28 @@ Adding a custom transport (say for one of the datastore on the Roadmap) is actua
};
```

### Custom Log Format
To specify custom log format you should set formatter function for transport. Currently supported transports are: Console, File, Memory.
Options object will be passed to the format function. It's general properties are: timestamp, level, message, meta. Depending on the transport type may be additional properties.

``` js
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
timestamp: function() {
return Date.now();
},
formatter: function(options) {
// Return string will be passed to logger.
return options.timestamp() +' '+ options.level.toUpperCase() +' '+ (undefined !== options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' );
}
})
]
});
logger.info('Data to log.');
```

### Inspirations
1. [npm][0]
2. [log.js][4]
Expand Down
4 changes: 4 additions & 0 deletions lib/winston/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ exports.log = function (options) {
//
// Remark: this should really be a call to `util.format`.
//
if (typeof options.formatter == 'function') {
return String(options.formatter(exports.clone(options)));
}

output = timestamp ? timestamp + ' - ' : '';
if (showLevel) {
output += options.colorize === 'all' || options.colorize === 'level' || options.colorize === true
Expand Down
3 changes: 2 additions & 1 deletion lib/winston/transports/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ Console.prototype.log = function (level, msg, meta, callback) {
raw: this.raw,
label: this.label,
logstash: this.logstash,
depth: this.depth
depth: this.depth,
formatter: this.formatter
});

if (level === 'error' || (level === 'debug' && !this.debugStdout) ) {
Expand Down
3 changes: 2 additions & 1 deletion lib/winston/transports/daily-rotate-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ DailyRotateFile.prototype.log = function (level, msg, meta, callback) {
label: this.label,
stringify: this.stringify,
showLevel: this.showLevel,
depth: this.depth
depth: this.depth,
formatter: this.formatter
}) + '\n';

this._size += output.length;
Expand Down
3 changes: 2 additions & 1 deletion lib/winston/transports/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ File.prototype.log = function (level, msg, meta, callback) {
timestamp: this.timestamp,
stringify: this.stringify,
label: this.label,
depth: this.depth
depth: this.depth,
formatter: this.formatter
}) + this.eol;

this._size += output.length;
Expand Down
5 changes: 3 additions & 2 deletions lib/winston/transports/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ Memory.prototype.log = function (level, msg, meta, callback) {
prettyPrint: this.prettyPrint,
raw: this.raw,
label: this.label,
depth: this.depth
depth: this.depth,
formatter: this.formatter
});

if (level === 'error' || level === 'debug') {
Expand All @@ -85,4 +86,4 @@ Memory.prototype.log = function (level, msg, meta, callback) {
Memory.prototype.clearLogs = function () {
this.errorOutput = [];
this.writeOutput = [];
};
};
11 changes: 6 additions & 5 deletions lib/winston/transports/transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ 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.formatter = options.formatter;

this.handleExceptions = options.handleExceptions || false;
this.exceptionsLevel = options.exceptionsLevel || 'error';
Expand Down
73 changes: 73 additions & 0 deletions test/custom-formatter-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* custom-formatter-test.js: Test function as formatter option for transport `{ formatter: function () {} }`
*
* (C) 2011 Charlie Robbins, Tom Shinnick, Andrii Melnyk
* MIT LICENSE
*
*/

var assert = require('assert'),
events = require('events'),
fs = require('fs'),
path = require('path'),
vows = require('vows'),
winston = require('../lib/winston'),
helpers = require('./helpers');

function assertFileFormatter (basename, options) {
var filename = path.join(__dirname, 'fixtures', 'logs', basename + '.log');

try { fs.unlinkSync(filename) }
catch (ex) { }

return {
topic: function () {
options.filename = filename;
var transport = new (winston.transports.File)(options);

// We must wait until transport file has emitted the 'flush'
// event to be sure the file has been created and written
transport.once('flush', this.callback.bind(this, null, filename));
transport.log('info', 'What does the fox say?', null, function () {});
},
"should log with the appropriate format": function (_, filename) {
var data = fs.readFileSync(filename, 'utf8');
assert.isNotNull(data.match(options.pattern));
}
}
}

vows.describe('winston/transport/formatter').addBatch({
"Without formatter": {
"with file transport": assertFileFormatter('customFormatterNotSetForFile', {
pattern: /info\:/,
json: false,
formatter: false
})
},
"When formatter option is used": {
"with file transport": {
"with value set to false": assertFileFormatter('customFormatterFalseValue', {
pattern: /info\:/,
json: false,
formatter: false
}),
"with value set to object ": assertFileFormatter('customFormatterObjectValue', {
pattern: /info\:/,
json: false,
formatter: {}
}),
"and function value with custom format": assertFileFormatter('customFormatter', {
pattern: /^\d{13,} INFO What does the fox say\?/,
json: false,
timestamp: function() {
return Date.now();
},
formatter: function(params) {
return params.timestamp() +' '+ params.level.toUpperCase() +' '+ (undefined !== params.message ? params.message : '') +
( params.meta && Object.keys(params.meta).length ? '\n'+ JSON.stringify(params.meta) : '' );
}
})
}
}
}).export(module);

0 comments on commit a34f7d2

Please sign in to comment.