From 12b7ee52b99b7acbec53e66d6b6ca8d4fb2f51f4 Mon Sep 17 00:00:00 2001 From: Tony <62355475+nTony46@users.noreply.github.com> Date: Tue, 6 Dec 2022 20:33:54 +0000 Subject: [PATCH 1/4] Added handling and tests for defaultMeta when using ECS winston format --- lib/winston/formatter/formatInput.js | 12 ++++++ lib/winston/logger.js | 2 + test/helpers/index.js | 3 +- test/unit/winston/formatter/transform.test.js | 38 +++++++++++++++++++ test/unit/winston/logger.test.js | 10 +++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 lib/winston/formatter/formatInput.js create mode 100644 test/unit/winston/formatter/transform.test.js diff --git a/lib/winston/formatter/formatInput.js b/lib/winston/formatter/formatInput.js new file mode 100644 index 000000000..c4bad286f --- /dev/null +++ b/lib/winston/formatter/formatInput.js @@ -0,0 +1,12 @@ +const { formatDefaultTransform } = require("./defaultTransform") +const { formatEcsTransform } = require("./ecsTransform") + +function formatInput(info, formatTransformName){ + const func = { + 'ecsTransform': formatEcsTransform, + }[formatTransformName] || formatDefaultTransform; + + return func(info); +} + +module.exports = { formatInput }; diff --git a/lib/winston/logger.js b/lib/winston/logger.js index 5f8758c89..99b6f2be5 100644 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -11,6 +11,7 @@ const { Stream, Transform } = require('readable-stream'); const asyncForEach = require('async/forEach'); const { LEVEL, SPLAT } = require('triple-beam'); const isStream = require('is-stream'); +const { formatInput } = require("./formatter/formatInput"); const ExceptionHandler = require('./exception-handler'); const RejectionHandler = require('./rejection-handler'); const LegacyTransportStream = require('winston-transport/legacy'); @@ -310,6 +311,7 @@ class Logger extends Transform { // (and re-throw) any errors generated by the user-provided format, but also // guarantee that the streams callback is invoked so that we can continue flowing. try { + info = formatInput(info, this.format.transform.name); this.push(this.format.transform(info, this.format.options)); } finally { this._writableState.sync = false; diff --git a/test/helpers/index.js b/test/helpers/index.js index fe51be9e3..06801a894 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -25,9 +25,10 @@ var helpers = exports; * @param {function} write Write function for the specified stream * @returns {Logger} A winston.Logger instance */ -helpers.createLogger = function (write, format) { +helpers.createLogger = function (write, format, defaultMeta) { return winston.createLogger({ format, + defaultMeta, transports: [ mockTransport.createMockTransport(write) ] diff --git a/test/unit/winston/formatter/transform.test.js b/test/unit/winston/formatter/transform.test.js new file mode 100644 index 000000000..d82ba7d25 --- /dev/null +++ b/test/unit/winston/formatter/transform.test.js @@ -0,0 +1,38 @@ +const assume = require("assume"); +const { formatInput } = require('../../../../lib/winston/formatter/formatInput'); + +describe('Format Info', function () { + describe('formatEcsTransform', function () { + it('should turn info.service from a string to an object', function() { + const info = { + level: 'info', + service: 'account' + }; + + const formattedInfo = formatInput(info, "ecsTransform"); + const expectedInfo = { + level: 'info', + service: {name: 'account'} + }; + + assume(formattedInfo).deep.equals(expectedInfo); + }); + }); + + describe('defaultTransform', function () { + it('should do nothing to the info', function() { + const info = { + level: 'info', + service: 'account' + }; + + const formattedInfo = formatInput(info, null); + const expectedInfo = { + level: 'info', + service: 'account' + }; + + assume(formattedInfo).deep.equals(expectedInfo); + }); + }); +}); diff --git a/test/unit/winston/logger.test.js b/test/unit/winston/logger.test.js index 83504f594..01659e484 100755 --- a/test/unit/winston/logger.test.js +++ b/test/unit/winston/logger.test.js @@ -21,6 +21,7 @@ const TransportStream = require('winston-transport'); const format = require('../../../lib/winston').format; const helpers = require('../../helpers'); const mockTransport = require('../../helpers/mocks/mock-transport'); +const mockEcsFormat = require('../../helpers/mocks/mock-ecsFormat'); const testLogFixturesPath = path.join(__dirname, '..', '..', 'fixtures', 'logs'); describe('Logger Instance', function () { @@ -920,6 +921,15 @@ describe('Logger Instance', function () { const log = logger.info; log('test'); }); + + it('adjust defaultMeta correctly to given format', (done) => { + let logger = helpers.createLogger(function (info){ + assume(info.service).is.a('object'); + done(); + }, mockEcsFormat(), {service: 'user-account'}); + logger.log({level: 'info'}); + }); + }); }); From e9db70c7d57a39d811b57f5cba95dd10f91c1c21 Mon Sep 17 00:00:00 2001 From: ryanDaliwal <116104728+ryanDaliwal@users.noreply.github.com> Date: Tue, 6 Dec 2022 20:40:08 +0000 Subject: [PATCH 2/4] add defaultTransform and ecsTransform functions --- lib/winston/formatter/defaultTransform.js | 6 ++++++ lib/winston/formatter/ecsTransform.js | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100644 lib/winston/formatter/defaultTransform.js create mode 100644 lib/winston/formatter/ecsTransform.js diff --git a/lib/winston/formatter/defaultTransform.js b/lib/winston/formatter/defaultTransform.js new file mode 100644 index 000000000..5dbe919b7 --- /dev/null +++ b/lib/winston/formatter/defaultTransform.js @@ -0,0 +1,6 @@ +const formatDefaultTransform = (info) => { + return info; +} + +module.exports = { formatDefaultTransform }; + diff --git a/lib/winston/formatter/ecsTransform.js b/lib/winston/formatter/ecsTransform.js new file mode 100644 index 000000000..3d6af7c5b --- /dev/null +++ b/lib/winston/formatter/ecsTransform.js @@ -0,0 +1,9 @@ +const formatEcsTransform = (info) => { + if (typeof info.service == "string"){ + info.service = {name: info.service}; + } + return info; +} + +module.exports = { formatEcsTransform }; + From 3c9c6920bd13899a1522dec830897ef57a7b51c3 Mon Sep 17 00:00:00 2001 From: jcai28 <111547253+jcai28@users.noreply.github.com> Date: Tue, 6 Dec 2022 22:57:41 +0000 Subject: [PATCH 3/4] added mock-ecsFormat file to avoid import elastic in test --- test/helpers/mocks/mock-ecsFormat.js | 57 ++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 test/helpers/mocks/mock-ecsFormat.js diff --git a/test/helpers/mocks/mock-ecsFormat.js b/test/helpers/mocks/mock-ecsFormat.js new file mode 100644 index 000000000..d7cc56688 --- /dev/null +++ b/test/helpers/mocks/mock-ecsFormat.js @@ -0,0 +1,57 @@ +const winston = require('../../../lib/winston'); +const { MESSAGE } = require('triple-beam'); + +/** + * Create a mock Winston format for ecs-logging output. + * + * @param {object} info object to be transformed + * @returns {object} object with ecs format + */ +function ecsTransform(info) { + const reservedFields = { + level: true, + 'log.level': true, + ecs: true, + '@timestamp': true, + err: true, + req: true, + res: true + }; + + const ecsFields = { + '@timestamp': new Date().toISOString(), + 'log.level': info.level, + message: info.message, + ecs: { "version":"1.6.0" } + }; + + const keys = Object.keys(info); + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; + if (!reservedFields[key]) { + ecsFields[key] = info[key]; + } + } + + const mockStringify = function(ecsFields) { + let serviceObject; + + if (typeof ecsFields.service === 'string'){ + for (let i=0; i <= ecsFields.service.length; i++){ + serviceObject[`${i}`] = ecsFields.service[i]; + } + } else { + serviceObject = ecsFields.service; + } + + const serviceString = JSON.stringify(serviceObject); + const ecsVersionString = JSON.stringify(ecsFields.ecs); + + return `{"@timestamp":"${ecsFields['@timestamp']}","log.level":${ecsFields['log.level']}","ecs":${ecsVersionString},"service":${serviceString}}`; + } + + info[MESSAGE] = mockStringify(ecsFields); + return info; +} + +module.exports = winston.format(ecsTransform); From eace047a8bdeb0675be2a9cccfa74d7bc745fdbb Mon Sep 17 00:00:00 2001 From: Tony <62355475+nTony46@users.noreply.github.com> Date: Sat, 10 Dec 2022 02:46:05 +0000 Subject: [PATCH 4/4] Fixed Linting Issues --- lib/winston/formatter/defaultTransform.js | 4 ++-- lib/winston/formatter/ecsTransform.js | 10 +++++----- lib/winston/formatter/formatInput.js | 14 +++++++------- lib/winston/logger.js | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/winston/formatter/defaultTransform.js b/lib/winston/formatter/defaultTransform.js index 5dbe919b7..8434e56e7 100644 --- a/lib/winston/formatter/defaultTransform.js +++ b/lib/winston/formatter/defaultTransform.js @@ -1,6 +1,6 @@ const formatDefaultTransform = (info) => { - return info; -} + return info; +}; module.exports = { formatDefaultTransform }; diff --git a/lib/winston/formatter/ecsTransform.js b/lib/winston/formatter/ecsTransform.js index 3d6af7c5b..8518189c1 100644 --- a/lib/winston/formatter/ecsTransform.js +++ b/lib/winston/formatter/ecsTransform.js @@ -1,9 +1,9 @@ const formatEcsTransform = (info) => { - if (typeof info.service == "string"){ - info.service = {name: info.service}; - } - return info; -} + if (typeof info.service === 'string') { + info.service = { name: info.service }; + } + return info; +}; module.exports = { formatEcsTransform }; diff --git a/lib/winston/formatter/formatInput.js b/lib/winston/formatter/formatInput.js index c4bad286f..54ed6bb2d 100644 --- a/lib/winston/formatter/formatInput.js +++ b/lib/winston/formatter/formatInput.js @@ -1,12 +1,12 @@ -const { formatDefaultTransform } = require("./defaultTransform") -const { formatEcsTransform } = require("./ecsTransform") +const { formatDefaultTransform } = require('./defaultTransform'); +const { formatEcsTransform } = require('./ecsTransform'); -function formatInput(info, formatTransformName){ - const func = { - 'ecsTransform': formatEcsTransform, - }[formatTransformName] || formatDefaultTransform; +function formatInput(info, formatTransformName) { + const func = { + ecsTransform: formatEcsTransform + }[formatTransformName] || formatDefaultTransform; - return func(info); + return func(info); } module.exports = { formatInput }; diff --git a/lib/winston/logger.js b/lib/winston/logger.js index 99b6f2be5..3a1184841 100644 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -11,7 +11,7 @@ const { Stream, Transform } = require('readable-stream'); const asyncForEach = require('async/forEach'); const { LEVEL, SPLAT } = require('triple-beam'); const isStream = require('is-stream'); -const { formatInput } = require("./formatter/formatInput"); +const { formatInput } = require('./formatter/formatInput'); const ExceptionHandler = require('./exception-handler'); const RejectionHandler = require('./rejection-handler'); const LegacyTransportStream = require('winston-transport/legacy');