Reputation: 679
My logger is set up like this:
const myFormat = printf(info => {
return `${info.timestamp}: ${info.level}: ${info.message}: ${info.err}`;
});
const logger =
winston.createLogger({
level: "info",
format: combine(timestamp(), myFormat),
transports: [
new winston.transports.File({
filename:
"./logger/error.log",
level: "error"
}),
new winston.transports.File({
filename:
"./logger/info.log",
level: "info"
})
]
})
Then I am logging out some error like this:
logger.error(`GET on /history`, { err });
How is it possible to log the full stack trace for errors to the File transport? I tried passing in the err.stack
and it came out as undefined
.
Upvotes: 67
Views: 53541
Reputation: 346
For me to get the stack trace with winston I had to use the following logger:
winston.createLogger({
level: 'debug',
format: winston.format.combine(
winston.format.errors({ stack: true }),
winston.format.metadata(),
),
transports: new winston.transports.Console(),
}),
Then you can add the following to make it look better:
winston.format.timestamp(),
winston.format.prettyPrint(),
Note that it wasn't enough for me to add format.errors, i also needed format.metadata
Upvotes: 0
Reputation: 5667
UPDATE 1/14/2021 - This no longer works in newer versions of Winston.
@Ming's answer got me partly there, but to have a string description with the error, this is how I got full stack tracing working on ours:
import winston from "winston";
const errorStackTracerFormat = winston.format(info => {
if (info.meta && info.meta instanceof Error) {
info.message = `${info.message} ${info.meta.stack}`;
}
return info;
});
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.splat(), // Necessary to produce the 'meta' property
errorStackTracerFormat(),
winston.format.simple()
)
});
logger.error("Does this work?", new Error("Yup!"));
// The log output:
// error: Does this work? Error: Yup!
// at Object.<anonymous> (/path/to/file.ts:18:33)
// at ...
// at ...
Upvotes: 12
Reputation: 83488
Here is another take for Winston 3.2.
Nowadays Winston comes with a built-in stacktrace formatter, but it does not seem to trigger if the same formatter has winston.format.simple()
combined. Thus, you need use winston.format.printf
instead as by the answer from Kirai Mali. I could not figure out how to configure both winston.format.errors()
and winston.format.simple()
in the same configuration.
Based on the current Winston README example and answers above, here is my configuration that uses JSON format logfiles, but for the local development console it still gives colored log lines and good stack traces.
// Use JSON logging for log files
// Here winston.format.errors() just seem to work
// because there is no winston.format.simple()
const jsonLogFileFormat = winston.format.combine(
winston.format.errors({ stack: true }),
winston.format.timestamp(),
winston.format.prettyPrint(),
);
// Create file loggers
const logger = winston.createLogger({
level: 'debug',
format: jsonLogFileFormat,
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' })
],
expressFormat: true,
});
// When running locally, write everything to the console
// with proper stacktraces enabled
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.errors({ stack: true }),
winston.format.colorize(),
winston.format.printf(({ level, message, timestamp, stack }) => {
if (stack) {
// print log trace
return `${timestamp} ${level}: ${message} - ${stack}`;
}
return `${timestamp} ${level}: ${message}`;
}),
)
}));
}
Upvotes: 14
Reputation: 657
Here is my logger configuration. Added errors({ stack: true })
, thanks to Murli Prajapati ans and small trick in printf function. My winston version is 3.2.1
.
const {format, transports} = require('winston');
const { timestamp, colorize, printf, errors } = format;
const { Console, File } = transports;
LoggerConfig = {
level: process.env.LOGGER_LEVEL || 'debug',
transports: [
new Console(),
new File({filename: 'application.log'})
],
format: format.combine(
errors({ stack: true }),
timestamp(),
colorize(),
printf(({ level, message, timestamp, stack }) => {
if (stack) {
// print log trace
return `${timestamp} ${level}: ${message} - ${stack}`;
}
return `${timestamp} ${level}: ${message}`;
}),
),
expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
colorize: false, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
ignoreRoute: function (req, res) {
return false;
} // optional: allows to skip some log messages based on request and/or response
}
I am using this same configuration in express-winston
and for general log also.
const winston = require('winston');
const expressWinston = require('express-winston');
/**
* winston.Logger
* logger for specified log message like console.log
*/
global.__logger = winston.createLogger(LoggerConfig);
/**
* logger for every HTTP request comes to app
*/
app.use(expressWinston.logger(LoggerConfig));
Upvotes: 7
Reputation: 9713
For winston version 3.2.0+
, following will add stacktrace to log output:
import { createLogger, format, transports } from 'winston';
const { combine, timestamp, prettyPrint, colorize, errors, } = format;
const logger = createLogger({
format: combine(
errors({ stack: true }), // <-- use errors format
colorize(),
timestamp(),
prettyPrint()
),
transports: [new transports.Console()],
});
Ref: https://github.com/winstonjs/winston/issues/1338#issuecomment-482784056
Upvotes: 46
Reputation: 6245
Here is my logger.js
with winston": "^3.1.0
const { createLogger, format, transports } = require('winston');
const { combine, timestamp, printf, colorize, splat } = format;
const myFormat = printf((info) => {
if (info.meta && info.meta instanceof Error) {
return `${info.timestamp} ${info.level} ${info.message} : ${info.meta.stack}`;
}
return `${info.timestamp} ${info.level}: ${info.message}`;
});
const LOG_LEVEL = process.env.LOG_LEVEL || 'debug';
const logger = createLogger({
transports: [
new (transports.Console)(
{
level: LOG_LEVEL,
format: combine(
colorize(),
timestamp(),
splat(),
myFormat
)
}
)
]
});
module.exports = logger;
Upvotes: 4
Reputation: 4300
You can write a formatter to pass error.stack
to log.
const errorStackFormat = winston.format(info => {
if (info instanceof Error) {
return Object.assign({}, info, {
stack: info.stack,
message: info.message
})
}
return info
})
const logger = winston.createLogger({
transports: [ ... ],
format: winston.format.combine(errorStackFormat(), myFormat)
})
logger.info(new Error('yo')) // => {message: 'yo', stack: "Error blut at xxx.js:xx ......"}
(the output will depend on your configuration)
Upvotes: 21