Winston not logging uncaught exceptions - node.js

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.

Related

Winston is not properly working, I am unable to get all the console values in log file using winston

I want to store all the console values in log file using Winstone, but I have ended up to store only the morgan values and not the console.log values in my log file.
And I also want to store the error values in my error.log file which I am unable to get it right now. Here below is my code.
winston.js file
var appRoot = require('app-root-path');
var winston = require('winston');
// define the custom settings for each transport (file, console)
var options = {
file: {
level: 'info',
filename: `${appRoot}/logs/app.log`,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
},
errorFile: {
level: 'error',
name: 'file.error',
filename: `${appRoot}/logs/error.log`,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 100,
colorize: true,
},
console: {
level: 'debug',
handleExceptions: true,
json: false,
colorize: true,
},
};
// instantiate a new Winston Logger with the settings defined above
var logger = winston.createLogger({
transports: [
new winston.transports.File(options.file),
new winston.transports.File(options.errorFile),
new winston.transports.Console(options.console)
],
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) {
logger.info(message);
},
};
module.exports = logger;
main.js file
const express = require('express');
const app=express();
const morgon=require("morgan");
var winston = require('./config/winston');
app.use(morgon("combined", { stream: winston.stream }));

How to info message and error message stored separate file using winston log file?

I tried to logging info and errors in log file using winston.If any info stored info.log. If uncaught exception errors occurred its stored only error.log file.but If commom errors are occurred its stored both file(info .log and error.log) how to fix it any one give some solution.
winston.js
const winston = require('winston');
require('winston-mongodb');
require('express-async-errors');
const winstonLogger = function () {
winston.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.simple(),
winston.format.timestamp(),
winston.format.prettyPrint(),
winston.format.colorize()
),
handleExceptions: true
}));
// Info Log messages to file
winston.add(new winston.transports.File({
filename: 'logs/info.log',
level: 'info'
}));
// Error Log Messages file
winston.add(new winston.transports.File({
filename: 'logs/error.log',
level: 'error',
handleExceptions: true,
}));
};
module.exports = winstonLogger;
I want info message stored on info.log file and error message stored on error.log file.uncaught exception error stored in separate file using winston
Winston logging is based on the level you specify. All logs below that level go to a specified file.
logging levels 0 to 5 (highest to lowest):
0: error
1: warn
2: info
3: verbose
4: debug
5: silly
Below is the sample code from winston documentation :
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' })
]
});
You can filter out logs by creating two loggers and adding name property to them.
This worked for me.
const winston = require('winston');
const infoLogger = winston.createLogger({
defaultMeta: { service: "log-service" },
transports: [
new winston.transports.File({
name: "info",
filename: "./logs/info.log",
level: "info",
})
],
});
const errorLogger = winston.createLogger({
defaultMeta: { service: "log-service" },
transports: [
new winston.transports.File({
name: "error",
filename: "./logs/error.log",
level: "error",
})
],
});
const logger = {
info: (params) => {
return infoLogger.info(params);
},
error: (params) => {
return errorLogger.error(params);
},
};
logger.info("info 1"); // Will go to info.log
logger.error("error 1"); // Will go to error.log
logger.info("info 2"); // Will go to info.log
logger.error("error 2 "); // Will go to error.log

Winston not Logging to console in typescript

I am confused by winston. I am using the following typescript code to log onto the console in my *.ts file:
import { Logger, LoggerInstance } from "winston";
const logger:LoggerInstance = new Logger();
logger.info('Now my debug messages are written to the console!');
the console remains empty. There are no compile errors or other issues.
At the same time the following works fine:
const wnstn = require("winston");
wnstn.info('Finally my messages are written to the console!');
Does anyone have a clue why that is the case? Do I have to configure the Logger differently? How would I use the defaults I get from the second example?
This is the Typescript way to import Winston.
First, be sure you have installed the typing :
npm i -D #types/winston
Then, in your script.ts
import { Logger, transports } from 'winston';
var logger = new Logger({
transports: [
new transports.Console(),
new transports.File ({ filename: 'somefile.log' })
]
});
In genral, you can import all constants and types without using winston.<...> before.
When you instantiate a new Logger instance you need to provide it a list of transports so it knows where to send the logs:
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'somefile.log' })
]
});
Well,
thanks to the hint of #idbehold , I found that a plain and easy:
import * as winston from "winston";
winston.info('Now my debug messages are written to the console!');
works for the default logger..
Well, I am following below file as winston.ts
import * as appRoot from 'app-root-path';
import * as winston from 'winston';
// define the custom settings for each transport (file, console)
const options = {
file: {
level: 'info',
filename: `${appRoot}/logs/app.log`,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
},
console: {
level: 'debug',
handleExceptions: true,
json: false,
colorize: true,
},
};
// instantiate a new Winston Logger with the settings defined above
const logger: winston.Logger = winston.createLogger({
transports: [
new winston.transports.File(options.file),
new winston.transports.Console(options.console)
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
const myStream = {
write: (message: string) => {
// use the 'info' log level so the output will be picked up by both transports (file and console)
logger.info(message);
}
};
export default logger;
as using inside app.ts as this.app.use(morgan('combined', { stream: winston.stream }));

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 log files with Winston?

We'd like to use Winston for our logging in Node.js. But, we can't figure out how to have two log files: one for just errors, and one for everything else.
Doing this the naive way doesn't work, however: adding multiple winston.transports.File transports gives an error.
Others have run into this problem, with vague hints of a solution, but no real answer.
Any ideas?
Unfortunately, the patch that pesho mentioned seems to be still not included in the official version (see stephenbeeson's comment in the pull request #149).
So, I used a workaround instead. As winston compares the name attributes, you can fool it by defining the name yourself:
winston = require 'winston'
logger = new winston.Logger
transports: [
new winston.transports.File
name: 'file#debug'
level: 'debug'
filename: '/tmp/debug.log'
new winston.transports.File
name: 'file#error'
level: 'error'
filename: '/tmp/error.log'
]
logger.error 'error' # both logs
logger.debug 'debug' # on debug log
Maybe not elegant, but at least it works.
In the meantime, you can implement a rudimentary wrapper using the same interface like so
var winston = require('winston');
var configs = require('./env.js');
var debug = new winston.Logger({
levels: {
debug: 0
},
transports: [
new (winston.transports.File)({ filename: configs.PATH_TO_LOG, level: 'debug'}),
new (winston.transports.Console)({level: 'debug'})
]
});
var info = new winston.Logger({
levels: {
info: 1
},
transports: [
new (winston.transports.File)({ filename: configs.PATH_TO_LOG, level: 'info'}),
new (winston.transports.Console)({level: 'info'})
]
});
var warn = new winston.Logger({
levels: {
warn: 2
},
transports: [
new (winston.transports.File)({ filename: configs.PATH_TO_LOG, level: 'warn'}),
new (winston.transports.Console)({level: 'warn'})
]
});
var error = new winston.Logger({
levels: {
error: 3
},
transports: [
new (winston.transports.File)({ filename: configs.PATH_TO_LOG, level: 'error'}),
new (winston.transports.Console)({level: 'error'})
]
});
var exports = {
debug: function(msg){
debug.debug(msg);
},
info: function(msg){
info.info(msg);
},
warn: function(msg){
warn.warn(msg);
},
error: function(msg){
error.error(msg);
},
log: function(level,msg){
var lvl = exports[level];
lvl(msg);
}
};
module.exports = exports;
This will cover the basic winston API. could be extended for metadata and so on...
I just sent a pull request that allows using multiple File transports in one logger.
https://github.com/flatiron/winston/pull/149
It is already merged into flatiron/winston.
You can also use my forked repo:
https://github.com/pdobrev/winston
You just need to give the transport a custom name property so you don't have a collision:
const logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ name: 'text', filename: logFile, json: false }),
new (winston.transports.File)({ name: 'json', filename: logFileJson })
]
});
You can read more about multiple transports in the docs: https://github.com/winstonjs/winston#multiple-transports-of-the-same-type
This feature is now officially supported in Winston and is addressed in the README here
Code example:
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' })
]
});
//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}

Resources