I have defined custom levels for my application .They are as follows.
protected levels: Level = {
"error": 0,
"warn": 1,
"info": 2,
"debug": 3,
"trace": 4
};
I am using daily file rotate transport to get daily log in separate files.
const options: Object = {
name: this.level,
filename: logFilePath,
dirname: WinstonLogAgent.DIR_LOG,
datePattern: "yyyyMMdd.",
prepend: true,
level: this.level,
levels: this.levels,
maxsize: this.maxFileSize,
maxFiles: this.maxFileCount,
handleExceptions: true,
humanReadableUnhandledException: true
};
this.transportInstance.push(new (winston.transports.DailyRotateFile)(options));
If i define log level to be 'info', it will create one log file named info.log and will log for levels 'info' , 'warn' and 'error' (trace and debug will be ignored).
But behaviour i wanted was different. If i am specifying level to be 'info' and i am logging levels 'info' , 'warn' and 'error' , then there should be separate files created for each type of log . i.e 'info' level should be logged to info.log and 'warn' level to be logged to warn.log.
I have tried specifying five different daily file rotate transport ,each with unique level. Then the problem i find is that there is duplicate log entries.
For example , if am logging 'error' level , it would log to info.log , warn.log & error.log when logging level is set to info.
How can i achieve my objective?
According to Winston's documentation, the default behavior is to log all the messages which have at least the specifies importance aka logging level.
Winston allows you to define a level property on each transport which specifies the maximum level of messages that a transport should log.
But there are ways to achieve your requirements.
I'll try to show you some of the possibilities, you can choose the method that works the best for you.
1. Custom Transports (Recommended):
You can create a custom transport and log only the levels you want.
Here is an example just to give you an idea:
let mainLogger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
]
});
class CustomTransport extends winston.Transport {
constructor(options) {
super(options);
this.name = 'customLogger';
this.level = options && options.level || 'info';
this.levelOnly = options && options.levelOnly;
this.levels = options && options.levels || [];
}
log(level, msg, meta, callback) {
if (!this.levelOnly || this.levels.indexOf(level) > -1) {
mainLogger[level](msg, meta);
}
callback(null, true);
}
}
winston.transports.CustomTransport = CustomTransport;
let myLogger = new winston.Logger({
transports: [
new (winston.transports.CustomTransport)({
levelOnly: true,
levels: ['info'],
}),
]
});
myLogger.info('will be logged');
myLogger.warn('will NOT be logged');
myLogger.info('will be logged as well');
2. Use winston-levelonly
This is a fork of the original winston package. The fork is at https://github.com/damianof/winston
This version adds a levelOnly option to make winston log only the specified level.
In the end, I would like to encourage you to read these relevant discussions:
- https://github.com/winstonjs/winston/issues/614
- https://github.com/winstonjs/winston/issues/812
- https://github.com/winstonjs/winston/pull/628
- Winston Logging - separate levels to separate Transports