I'm using Winston in Node.js for logging. I know I can add metadata individually to each log message but is there a way to specify a default set of metadata that'll be added to every log message (such as the app name) as I don't want to specify it every time I need to send a log message.
-
There is now a documented way to do this, see my answer. – DrakaSAN Sep 01 '16 at 07:38
7 Answers
For Winston v2 (see comments)
There are now rewriters
.
For example, the below will add a property app
to every metadata going through this logger.
logger.rewriters.push(function(level, msg, meta) {
meta.app = 'myApp';
return meta;
});
You can also declare it when building the logger:
new (winston.Logger)({
level: config.log[file].level,
rewriters: [
(level, msg, meta) => {
meta.app = 'myApp';
return meta;
}
],
transports: [
/*your transports*/
]
});

- 10,680
- 4
- 46
- 63

- 7,673
- 7
- 52
- 94
-
3winston v3 seems to remove the possibility to mutate the metadata. It means that @Jesse is the preferred solution for winston v3 & + if you want to add metadata. If the output log is a string and not JSON, a custom format can do the job (cf github.com/winstonjs/winston/issues/1140) – Thierry Abaléa Nov 11 '17 at 18:09
-
@ThierryAbaléa: Thanks for the tip, I ll try out the custom format solution, and update my answer accordingly – DrakaSAN Nov 13 '17 at 11:34
-
1The release Winston v3 does allow mutating the metadata, and the issue mentioned by Thierry helped to get an example added to the migration guide and was how I found it too. I have added another answer with the new way. – shadowspawn Aug 07 '18 at 05:46
For Winston v3:
const addAppNameFormat = winston.format(info => {
info.appName = "My Program";
return info;
});
const logger = winston.createLogger({
format: winston.format.combine(
addAppNameFormat(),
winston.format.json()
),
transports: [new winston.transports.Console()]
});
logger.warn('Danger Will Robinson!');
// {"message":"Danger Will Robinson!","level":"warn","appName":"My Program"}

- 3,039
- 22
- 26
There is now (8/20/19) a property defaultMeta
that is passed to createLogger
that will inject the meta you specify to every log.
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
defaultMeta: { service: 'user-service' },
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});

- 965
- 11
- 19
There's no built-in way to do this, but you can definitely add it yourself - here's how:
First, set up your logger like you normally would. For example:
var logger = new (winston.Logger)({
"exitOnError" : true,
"transports" : [
new (winston.transports.Console)({ "colorize" : true, "level" : "silly", "silent" : false, "handleExceptions" : false }),
]
});
Then override the log() method (this is always called by the level methods - logger.foo()
actually calls logger.log('foo')
.)
logger.log = function(){
var args = arguments;
if(args[2]) args[3] = args[2];
args[2] = {
"foo" : "bar"
}
winston.Logger.prototype.log.apply(this,args);
}
All I'm doing above is making it so when logger.log()
is called, it instead calls the above method, which adds the metadata (in this case, an object containing a foo
key). Then it calls winston's Logger.log method from the proper context.
The above code would be in a module you create, at the bottom just export the logger:
module.exports = logger;
and import the logger module instead of the winston module in your sub classes.
var logger = require('./logger.js');
Hope that helps!

- 10,370
- 10
- 62
- 81
-
1Note: this will overwrite any metadata you specify in the log statement. You can use underscore's `_.defaults()` to augment it, or you could add a check for args[2] and not overwrite it if it exists to get around this. – Jesse Feb 22 '12 at 18:26
-
1Instead of overwriting the arguments, just append them: logger.log = function(){ var args = arguments; if(args[2]) { args[2].foo = "bar" } winston.Logger.prototype.log.apply(this,args); } – harryBundles Apr 28 '16 at 12:17
-
-
2@DrakaSAN winston v3 seems to remove the possibility to mutate the metadata cf https://github.com/winstonjs/winston/issues/1140 – Thierry Abaléa Nov 11 '17 at 18:04
Another option with an output more like log4j(s):
There is a documented label
property which will add a label to the output (json or line):
var _ = require('lodash');
var winston = require('winston');
var path = require('path');
var baseDir = path.resolve(__dirname, '..');
// SETUP WINSTON LOGGER
var container = new winston.Container();
container.add("exception", {
console: {
handleExceptions: true,
timestamp: true,
label: "EXCEPTION",
colorize: true
}
});
container.get("exception").exitOnError = false;
var keys = [];
module.exports = function(filename) {
var label = path.relative(baseDir, filename);
if (!_.contains(keys, label)) {
container.add(label, {
console: {
handleExceptions: false,
level: 'debug',
timestamp: true,
label: label,
colorize: true
}
});
keys.push(label);
}
var logger = container.get(label);
logger.exitOnError = false;
return logger;
};
And in the other modules require it like this:
var logger = require('./logger')(__filename);
Example output:
2014-07-23T07:05:27.770Z - info: [config/config.js] .......

- 10,680
- 4
- 46
- 63

- 16,058
- 2
- 88
- 91
I was looking for a way to add the github delivery ID to all my logs.
I use winston 3 and defaultMeta
getters along with express-http-context
// logger.js
const logger = (filename) => winston.createLogger({
...
defaultMeta: {
get deliveryId () { return httpContext.get('deliveryId'); },
get deliveryEvent () { return httpContext.get('deliveryEvent'); },
module: filename,
},
...
});
module.exports = (fileName) => {
return logger(fileName);
}
in my other modules:
// foo.js
const logger = require('./logger')(__filename)
module.exports = async(someInput) => {
logger.debug('hello ' + someInput)
}
https://github.com/winstonjs/winston/issues/1626#issuecomment-531142958

- 2,451
- 2
- 23
- 31
-
Combining the 'get' is NICE and also very useful because it turns the defaultMeta into a dynamic object – Aharon Ohayon Jun 19 '22 at 00:01
I've found a better way using util-extend based on what I read on this blog. It will append the data in all cases, which I found useful for catching logger.info vs logger.log("info", message) and won't overwrite your other arguments.
logger.log = function(){
var args = arguments;
var level = args[0];
var newArgs = {
foo: "bar",
baz: "abc"
};
var originalMeta = args[2] || {};
args[2] = extend(originalMeta, newArgs);
winston.Logger.prototype.log.apply(this,args);
};
Will output in the console and in your logs.

- 150
- 3
- 15