e.g.
not working
// err object was created by new Error('failed')
winston.error('An error happened:', { error: err, bar: "foo" });
// => An error happened: { error: {}, bar: "foo" }
winston.error('An error happened:', { errors: [err, err, err] });
// => An error happened: { errors: [{},{},{}] }
works well, if top level is Error itself
winston.error('An error happened:', err);
Shouldnt the correct syntax be
'''
// err object was created by new Error('failed')
winston.error('An error happened: %j', { error: err, bar: "foo" });
// => An error happened: { error: {}, bar: "foo" }
winston.error('An error happened: %j', { errors: [err, err, err] });
// => An error happened: { errors: [{},{},{}] }
'''
Not sure about winstons implementation but doing console.log("",var) is different from console.log("%s/j",var); I think in the previous case console logger just concatenates the two objects while the the latter it actually typecasts the variable and interpolates it with its corresponding placeholder.
https://github.com/winstonjs/winston#string-interpolation
Has a more precise description
I got the same issue - it seems to be caused by the naive cloning done in the cycle library's decycle function (https://github.com/dscape/cycle/blob/ab67ce90e8fa2efdb8f21074661366ec56f6a724/cycle.js#L91) - Error properties are non-enumerable and so nothing gets copied into the "clone" (it returns {}).
This is called from within winston to process the metadata on each log call here - https://github.com/winstonjs/winston/blob/de69bccf957cca2247ef529c2b66c88059adbae6/lib/winston/common.js#L142 .
It would seem like an upstream PR to cycle would be the correct fix, either to iterate non-enumerable properties or perform some other more robust form of cloning. If you just wanted to fix it for your usage, a rewriter can do the job - you have to essentially 'pre-clone' the error objects before they get passed to cycle.
Here's a crude rewriter using lodash 3.x's merge (mergeWith in 4.x) with a customiser which addresses the issue:
rewriters.push(function(level, msg, meta) {
return _.merge({}, meta, function errorCloner(objValue, srcValue) {
if(srcValue instanceof Error) {
var clone = {};
// Make sure we clone both enumerable and non-enumerable properties on errors
Object.getOwnPropertyNames(srcValue).forEach(function(prop) {
var value = srcValue[prop];
clone[prop] = value && typeof value === 'object' ?
// Recurse for objects, to handle inner exceptions
_.mergeWith({}, value, errorCloner) :
value;
});
return clone;
}
});
});
Hopefully that might be of some use to anyone else who gets the same problem.
This is effectively the same bug from https://github.com/winstonjs/winston/issues/280 (cycle cloning an error object to be empty because error properties are non-enumerable). That took a year to fix. We're just 15 months from this original report to today. Or you could say it's been 4 years and the original bug has only been partially fixed.
I was facing the same issue so i wrote this package, utils-deep-clone. Check it out.
P.S. I didn't do it in winston itself because i saw the PR's section and i guess it's a dead project.
I was facing the same issue so i wrote this package, utils-deep-clone. Check it out.
P.S. I didn't do it in
winstonitself because i saw the PR's section and i guess it's a dead project.
sounds good, Thanks Atishay!
Most helpful comment
I was facing the same issue so i wrote this package, utils-deep-clone. Check it out.
P.S. I didn't do it in
winstonitself because i saw the PR's section and i guess it's a dead project.