-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
It looks like 3.0 is logging {} for Error objects #1243
Comments
A workaround:
Hope it helps. |
Workaround didn't work for me (info.message is getting lost somewhere) Variant workaround: const winston = require('winston')
const MESSAGE = Symbol.for('message')
/*
* function replacer (key, value)
* Handles proper stringification of Buffer output.
*/
const replacer = function (key, value) {
return value instanceof Buffer
? value.toString('base64')
: value
}
var json_log = winston.format(function (info, opts) {
var display = info
if (info._error) {
display = Object.assign({}, info, { message: info._error })
delete display._error
}
info[MESSAGE] = JSON.stringify(display, opts.replacer || replacer, opts.space)
return info
})
var preserve_error_message = format(function (info, opts) {
if (_.isError(info)) {
info._error = info.message
}
return info
})
const logger = winston.createLogger({
levels: ...,
format: format.combine(format.timestamp(), preserve_error_message()),
transports: [
new transports.Console({
level: this.config.console.level,
format: json_log({ space: 2 })
})
] That doesn't seem particularly elegant, so an official to preserve |
I'm running into this as well. Shouldn't winston handle this out of the box? @indexzero what do you think about this? |
After looking at the logform json implementation I now see how the opts.replacer is supposed to be used and I came up with another solution when combining this stackoverflow post with the existing Buffer stringification: 'use strict';
const winston = require('../');
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.json({ replacer: replaceErrors })
),
transports: [
new winston.transports.Console(),
]
});
function replaceErrors(key, value) {
if (value instanceof Buffer) {
return value.toString('base64');
} else if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (key) {
error[key] = value[key];
});
return error;
}
return value;
}
var error = new Error('foooo');
error.my_custom_stuff = 'bar';
logger.log('error', 'Hello, this is a raw logging event', { error }); which prints:
I no longer think this should be handled outside the box, because I think a logging library should not determine how your error should be serialized into a log message, you define that yourself. |
Not sure of your exact use case but why aren't you logging errors directly:
(That works as of #1234). If you do need the error object inside a larger object you're logging, then it's worth noting Node.js |
Going to go ahead and mark this closed, feel free to re-open or make a new issue if new problems/questions arise! Thanks! |
Not even
And it works quite well! |
|
More concise version: function format() {
const replaceError = ({ label, level, message, stack }) => ({ label, level, message, stack });
const replacer = (key, value) => value instanceof Error ? replaceError(value) : value;
return combine(label({ label: 'ssr server log' }), format.json({ replacer }));
}
const logger = createLogger({
format: format(),
}); But this is what I actually do to have pretty logs locally and JSON errors in production: function prodFormat() {
const replaceError = ({ label, level, message, stack }) => ({ label, level, message, stack });
const replacer = (key, value) => value instanceof Error ? replaceError(value) : value;
return combine(label({ label: 'ssr server log' }), format.json({ replacer }));
}
function devFormat() {
const formatMessage = info => `${info.level} ${info.message}`;
const formatError = info => `${info.level} ${info.message}\n\n${info.stack}\n`;
const format = info => info instanceof Error ? formatError(info) : formatMessage(info);
return combine(colorize(), printf(format))
}
const logger = createLogger({
level: process.env.LOG_LEVEL || 'info',
exitOnError: false,
transports: [new transports.Console()],
format: isProd ? prodFormat() : devFormat(),
}); which gives me this in production and this in development |
I wrote this to support custom error classes with unknown properties, and also, to clean up the stack because those newlines are horrible in json-based logging.
result:
|
I made an example for local development environment and |
I was facing the same issue so i wrote this package, utils-deep-clone. Check it out. |
You can fix this via a replacer on the json format options that pulls out the non-enumerable message and stack props into a new plain enumerable object for logging. import { createLogger, format } from 'winston'
import { Console } from 'winston/lib/winston/transports'
const serializeError = ({ message, stack, ...rest }: Error): object => ({
message,
stack,
...rest,
})
const logger = createLogger({
transports: [
new Console({
format: format.json({ replacer: (_key, value) => (value instanceof Error ? serializeError(value) : value) })
}),
],
}) |
Sequelize does its magic deleted_at paranoid thing and causes non obvious failure. Winston 3 it looks like won't log an error if you try, see: winstonjs/winston#1243 Co-authored-by: Rosie Amphlett <rosie.amphlett1@nhs.net> Co-authored-by: syedsadiqali <syed.ali69@nhs.net>
Hi All
I am having some hassle with winston 3.0 logging empty error objects when it is using a json format.
logs the expected
while
logs the erroneous
when it is passed
Manually creating a format with
also returned the erroneous result.
Does anybody know of a workaround for this?
The text was updated successfully, but these errors were encountered: