diff --git a/lib/winston/logger.js b/lib/winston/logger.js index 829c62f0c..435363341 100644 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -48,11 +48,12 @@ class Logger extends Transform { write: { value: function (info) { const infoClone = Object.assign( - {}, + Object.create(Object.getPrototypeOf(info)), defaultRequestMetadata, info ); + // Object.create preserves the prototype chain but // Object.assign doesn't copy inherited Error // properties so we have to do that explicitly // diff --git a/test/unit/winston/logger.test.js b/test/unit/winston/logger.test.js index 6621f6a80..c14eb3ec7 100755 --- a/test/unit/winston/logger.test.js +++ b/test/unit/winston/logger.test.js @@ -988,6 +988,31 @@ describe('Logger Instance', function () { childLogger.error(Error('dummy error', { cause: Error('dummy error cause') })); }); +it('preserves prototype of info object in child logger', (done) => { + class CustomError extends Error { + constructor(message) { + super(message); + this.custom = true; + } + } + + const assertFn = ((msg) => { + assume(msg.level).equals('error'); + assume(msg.custom).is.true(); + assume(msg.requestId).equals('123'); + done(); + }); + + const logger = winston.createLogger({ + transports: [ + mockTransport.createMockTransport(assertFn) + ] + }); + + const childLogger = logger.child({ requestId: '123' }); + childLogger.error(new CustomError('custom error')); + }); + it('defaultMeta() autobinds correctly', (done) => { const logger = helpers.createLogger(info => { assume(info.message).equals('test');