How can I add timestamp to logs using Node.js library Winston?
node.jsLoggingWinstonnode.js Problem Overview
I want to add timestamp to logs. What is the best way to achieve this?
node.js Solutions
Solution 1 - node.js
Above answers did not work for me. In case you are trying to add timestamp to your logs using the latest version of Winston - 3.0.0-rc1, this worked like charm:
const {transports, createLogger, format} = require('winston');
const logger = createLogger({
format: format.combine(
format.timestamp(),
format.json()
),
transports: [
new transports.Console(),
new transports.File({filename: 'logs/error/error.log', level: 'error'}),
new transports.File({filename: 'logs/activity/activity.log', level:'info'})
]
});
I used 'format.combine()'. Since I needed timestamp on all my transports, I added the formatting option within the createLogger, rather than inside each transport. My output on console and on file (activity.log) are as follows:
{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}
{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}
We can add formatting to this timestamp in 'format.combine()' as usual using:
format.timestamp({format:'MM-YY-DD'})
Solution 2 - node.js
I was dealing with the same issue myself. There are two ways I was able to do this.
When you include Winston, it usually defaults to adding a Console transport. In order to get timestamps to work in this default case, I needed to either:
- Remove the console transport and add again with the timestamp option.
- Create your own Logger object with the timestamp option set to true.
The first:
var winston = require('winston');
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {'timestamp':true});
The second, and cleaner option:
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({'timestamp':true})
]
});
Some of the other options for Console transport can be found [here][1]:
- level: Level of messages that this transport should log (default 'debug').
- silent: Boolean flag indicating whether to suppress output (default false).
- colorize: Boolean flag indicating if we should colorize output (default false).
- timestamp: Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.
[1]: https://github.com/winstonjs/winston#console-transport "here"
Solution 3 - node.js
We can do like this also
var winston = require('winston');
const { createLogger, format, transports } = require('winston');
var config = require('../configurations/envconfig.js');
var loggerLevel = process.env.LOGGERLEVEL || config.get('LOGGERLEVEL');
var logger = winston.createLogger({
format: format.combine(
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}),
format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`+(info.splat!==undefined?`${info.splat}`:" "))
),
transports: [
new (winston.transports.Console)({ level: loggerLevel }),
]
});
module.exports = logger;
Solution 4 - node.js
You can use built-in util and forever to achieve logging with timestap for your nodejs server. When you start a server add log output as part of the parameter:
forever start -ao log/out.log server.js
And then you can write util in your server.js
server.js
var util = require('util');
util.log("something with timestamp");
The output will look something like this to out.log file:
out.log
15 Mar 15:09:28 - something with timestamp
Solution 5 - node.js
I took Biswadev's answer and created a stringified JSON object. This way if i need to process the logs later it will be in a well structured format.
const winston = require('winston');
const { createLogger, format, transports } = require('winston');
const dotenv = require('dotenv');
dotenv.config();
var logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
format.printf((info) =>
JSON.stringify({
t: info.timestamp,
l: info.level,
m: info.message,
s: info.splat !== undefined ? `${info.splat}` : '',
}) + ','
)
),
});
if (process.env.NODE_ENV !== 'PRODUCTION') {
logger.add(new transports.Console({ format: winston.format.cli() }));
// Turn these on to create logs as if it were production
// logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
// logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
// logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
} else {
logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
}
module.exports = {
logger,
};
Usage:
app.listen(port, () => logger.info(`app is running on port ${port}`));
Output:
info.log file:
{"t":"2020-08-06 08:02:05","l":"info","m":"app is running on port 3001","s":""},
Console:
info: app is running on port 3001
Solution 6 - node.js
Although I'm not aware of winston, this is a suggestion. I use log4js for logging & my logs by default look like this
[2012-04-23 16:36:02.965] [INFO] Development - Node Application is running on port 8090
[2012-04-23 16:36:02.966] [FATAL] Development - Connection Terminated to '127.0.0.1' '6379'
Development is the environment of my node process & [INFO|FATAL] is log level
Maintaining different profiles for logging is possible in log4js. I have Development & Production profiles. Also there are logger types like rolling file appender, console appender, etc. As a addon your log files will be colorful based on the log level [Trace, Info, Debug, Error, Fatal] ;)
log4js will override your console.log It is a configurable parameter now in 0.5+
Solution 7 - node.js
we could use console-stamp to add timestamp and log level to the existing console: require('console-stamp')(console, '[yyyy-mm-dd HH:MM:ss.l]')
See https://github.com/starak/node-console-stamp for the details
Solution 8 - node.js
Sometimes default timestamp format can be not convenient for you. You can override it with your implementation.
Instead of
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({'timestamp':true})
]
});
you can write
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
'timestamp': function() {
return <write your custom formatted date here>;
}
})
]
});
See https://github.com/winstonjs/winston#custom-log-format for the details
Solution 9 - node.js
Another solution is wrapping the logger into a file that exports some functions like logger.info(), logger.error(), etc. then you just pass an extra key to be sent on every message log.
loggerService.js
const logger = winston.createLogger({ ... })
function handleLog(message, level) {
const logData = {
timestamp: Date.now(),
message,
}
return logger[level](logData)
}
function info(message) {
handleLog(message, 'info')
}
function error(message) {
handleLog(message, 'error')
}
function warn(message) {
handleLog(message, 'warn')
}
module.exports = {
info,
error,
warn
}
whatever-file.js
const logger = require('./services/loggerService')
logger.info('Hello World!')
your-log.log
{"timestamp":"2019-08-21 06:42:27","message":"Hello World!","level":"info"}