winston log level/ hide log levels - node.js

As far as I understood has Winston a hierarchy in its logging levels. You can set the level with winston.level = 'error' and all levels below should not be shown. Unfortunately I still get the logs of info and debug shown in my console.
Question 1):
How to really set winston to show me only the log level
Question 2)
Why is Debug anyways shown in the console, I configured it to show up in a log file (what it additionally does)
winston = require('winston')
winston.emitErrs = true
logger = new winston.Logger({
transports: [
new winston.transports.File({
level: 'info'
filename: 'logs/log.log'
handleExceptions: true
json: true
maxsize: 5242880 #5MB
maxFiles: 5
colorize: false
timestamp: true
}),
new winston.transports.Console({
level: 'debug'
handleExceptions: true
json: false
colorize: true
})
],
exitOnError: false
})
winston.level = 'error'
module.exports = logger
module.exports.stream = {
write: (message, encoding) ->
logger.info(message)
}
The code is basically from this tut:
http://tostring.it/2014/06/23/advanced-logging-with-nodejs/

Now I got the concept. It logs everything up to the log level in the defined transport. So I guess it is not possible to stream debug just to console and info to the log without manipulating the order.
This does not log debug in the console:
new winston.transports.Console({
level: 'info'
handleExceptions: true
json: false
colorize: true
})
My first assumption was that I can specify a transport for each log level and then decide how much logging I want to have with:
winston.setLevels(winston.config.syslog.levels)
e.g.
error to mongoDb
info to log.log file
debug to console

Related

Winston not logging uncaught exceptions

I'm trying to use winston to log unhandled exceptions to file and console. The problem is that it is not logging them. Here my setup:
var winston = require('winston');
let file = process.env.APP_TOOL_SET_API_PROJECT+"/logs/app.log";
console.log(process.env.APP_TOOL_SET_API_PROJECT);
// define the custom settings for each transport (file, console)
var options = {
file: {
level: 'info',
filename: file,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
},
console: {
level: 'debug',
handleExceptions: false,
json: true,
colorize: true,
},
};
// instantiate a new Winston Logger with the settings defined above
var logger = winston.createLogger({
format: winston.format.combine(
//winston.format.label({ label: '[my-label]' }),
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}),
//
// The simple format outputs
// `${level}: ${message} ${[Object with everything else]}`
//
winston.format.simple(),
//
// Alternatively you could use this custom printf format if you
// want to control where the timestamp comes in your final message.
// Try replacing `format.simple()` above with this:
//
winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`)
),
transports: [
new winston.transports.File(options.file),
new winston.transports.Console(options.console)
],
exceptionHandlers: [
new winston.transports.File({ filename: process.env.APP_TOOL_SET_API_PROJECT+"/logs/exceptions.log" }),
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
write: function(message, encoding) {
// use the 'info' log level so the output will be picked up by both transports (file and console)
logger.info(message);
},
};
module.exports = logger;
To add a bit more of information, if I wrap a thrown exception with setTimer it then is logged correctly.
setTimeout(() => {
throw new Error('hello world');
}, 250);
But this only would work for user thrown exceptions and feels really ugly to have to wrap each throw with setTimeout.
Is there any solution for this?
Well, just after posting the answer, my mental background thread spit the possible problem.
Obviously I was throwing the exception (just testing) too early and I wasn't given winston enough time to init properly.
This is why waiting with the setTimer was logging correctly.

winston-daily-rotate-file prepend option not working

I have my winston setup as follows
// Config import.
var config = require('../config');
// Library imports.
var winston = require('winston');
var logger = new(winston.Logger)({
transports: [
new(winston.transports.Console)({
level: 'debug',
colorize: true,
timestamp: true,
json: true,
showLevel: true
}),
new(require('winston-daily-rotate-file'))({
prepend: true,
level: 'debug',
colorize: true,
timestamp: true,
filename: 'log.txt',
maxSize: config.log.maxSize,
json: true,
prettyPrint: true
})
]
});
It logs to the console fine - as expected.
It logs to file fine - as expected.
However, the filename has the date tacked onto the end of the filename, not the beginning, like the prepend option would suggest.
Is anyone able to offer any insight into this?
Worked this one out - I'm a bit silly.
The version showing in master on the project's github page is not the same as the version that is dished out by npm install - the version that is served via npm doesn't currently have support for the prepend option.
Hopefully a release is coming soon :)

Logging only the message using winston

I am using winston logger in my node app and i want to log my custom message to the log file.
var logger = new winston.Logger({
transports: [
new winston.transports.File({
level: 'info',
filename: '/tmp/test.log',
handleExceptions: true,
json: true,
maxsize: 20971520 //20MB
})
],
exitOnError: false
});
I only need to log message in the log, i dont need to log level and timestamp in the log file. Current logged sample is as below.
{"level":"info","message":"sample entry to log","timestamp":"2015-12-11T09:43:50.507Z"}
My intention is to get entry in the log file as below
sample entry to log
How to achieve this?
Winston 3:
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
transports: [
new winston.transports.Console({
format: winston.format.printf(log => log.message),
})
]
});
logger.info('eat my shorts');
On Winston 2.x
If you want to print only the message, you can achieve this by setting:
json: false,
timestamp: false,
showLevel: false
Full Logger example:
let logger = new Logger({
transports: [
new (transports.File)({
name: 'info-file',
filename: 'filelog-info.log',
json: false,
timestamp: false,
showLevel: false
})
],
exitOnError: false
});
logger.log('info', 'eat my shorts');
gives in filelog-info.log: eat my shorts
FYI: filters and rewriters didn't help here
If anyone, as did I, finds this question in hopes of making express-winston log only message (to the console in my case)
Here is what I did:
const winston = require('winston');
const expressWinston = require('express-winston');
const { MESSAGE } = require('triple-beam');
expressWinston.logger({
transports: [
new winston.transports.Console({
format: simpleformatter()
})
]
});
const simpleformatter = winston.format(info => {
info[MESSAGE] = info.message;
return info;
});
Yep got the one i was looking for
https://github.com/winstonjs/winston#filters-and-rewriters
https://github.com/winstonjs/winston#custom-log-format

Multiple file transports in using Winston

I am attempting to use multiple transports in Winston. This is working...sorta. I have a transport set up for the app's audit log, with a custom level of 'audit', and a transport for 'info'.
var winston_mongo_options = {
level: 'audit', // level that should be logged
safe: true, //makes sure writes happen before firing log event
db: config.db.db, // db in which to write logs
host: config.db.host,
port: config.db.port,
collection: config.db.audit_collection // collection we want logging to occur
};
if (config.db.user) {
winston_mongo_options.username = config.db.user;
winston_mongo_options.password = config.db.pass;
}
var custom_levels = winston.config.syslog.levels;
custom_levels.audit = 8;
var logger = new (winston.Logger)({
levels: custom_levels,
transports : [
new (winston.transports.MongoDB)(winston_mongo_options),
new (winston.transports.File)({
level: 'info',
silent: false,
colorize: true,
timestamp: true,
filename: config.logs.debug,
maxsize: 500000,
maxFiles: 5,
json: true
})
],
exceptionHandlers: [
new (winston.transports.File)({
silent: false,
colorize: false,
timestamp: true,
filename: config.logs.exception,
maxsize: 500000,
maxFiles: 5,
json: true
})
]
});
module.exports.logger = logger;
Obviously, I'm requiring this file where/when I want to do any logging. The problem comes in when wanting to send certain information separately to the logs.
logger.audit('Server Started - to DB');
logger.info('Server Started - to info');
These two lines should write to separate logs. The first line gets properly written to the database AND to the info log file. What am I doing wrong?
SOLVED: The problem was how I am defining the levels. I didn't realize that the way Winston logging works, is a log will receive everything >= the level defined. So my 'info' transport being a level 0 was receiving messages sent to the 'audit' transport, which was a level 8. I set 'audit' to level 0, and it stopped showing up in the 'info' log. I then found a better solution by creation a whole new logger just for the audit database log.

Winston: how to rotate logs

How can I rotate logs when using Winston to handle logging for node.js. That is, how can I create a new file for each day the app runs?
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: '2012-07-09.log' })
]
});
logger.log('info', 'Test Log Message', { anything: 'This is metadata' });
winston author and maintainer here.
Logging to a new file everyday is currently an open feature request: https://github.com/flatiron/winston/issues/10. Would love to see someone implement it.
That said, there are other options:
The File transport accepts a maxsize option which will rotate the logfile when it exceeds a certain size in bytes.
There is also an open pull-request with a new transport I haven't had a chance to really dig into "fileRotate", which it seems does this kind of date-based rotation: https://github.com/flatiron/winston/pull/120/files
The feature is present and we are using it in production, winston.transports.DailyRotateFile:
var timeFormatFn = function() {
'use strict';
return moment().format(cfg.timeFormat);
};
var logger = new(winston.Logger)({
exitOnError: false,
transports: [
new(winston.transports.DailyRotateFile)({
filename: cfg.appLogName,
dirname: __dirname + '/../' + cfg.logsDirectory,
datePattern: cfg.rollingDatePattern,
timestamp: timeFormatFn
}),
new(winston.transports.Console)({
colorize: true,
timestamp: timeFormatFn
})
]
});
You can use the following code to rotate the log files daily:
var winston = require('winston');
require('winston-daily-rotate-file');
var transport = new (winston.transports.DailyRotateFile)({
filename: './log',
datePattern: 'yyyy-MM-dd.',
prepend: true,
level: 'info'
});
var logger = new (winston.createLogger)({
transports: [
transport
]
});
logger.info('Hello World!');
According to the author of winston-filerotatedate it is a:
File transport for winston that allows the log files to be rotated depending on size and time.
The File transport accepts a filename via the 'filename' option and uses that file as the primary logging target.
Should the file grow past 'maxsize' bytes then the current log file is renamed and a new primary log tile is created.
The name of the renamed log file is formated as such 'basenameYYYYMMDD[a-z].bak'.
Available options are:
level: Level of messages that this transport should log.
silent: Boolean flag indicating whether to suppress output.
timestamp: Boolean flag indicating if we should prepend output with timestamps (default true). If function is specified, its return value will be used instead of timestamps.
filename: The filename of the logfile to write output to.
dirname: The folder the logfile will be created in.
maxsize: Max size in bytes of the logfile, if the size is exceeded then a new file is created.
json: If true, messages will be logged as JSON (default true).
Other people have already given good answers for this problem. But for those people looking for an example of how to do this in more modern JavaScript syntax(ES6 and beyond) using winston-daily-rotate-file, the following code should help:
const { createLogger, transports } = require('winston');
require('winston-daily-rotate-file');
const logger = createLogger({
level: 'info',
transports: [
new transports.DailyRotateFile({
filename: 'info-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
level: 'info'
})
]
});
logger.log('info', 'Test Log Message', { anything: 'This is metadata' });
As of Dec 18, 2012, this feature is now available in Winston (see https://github.com/flatiron/winston/pull/205)

Resources