From aedef32bb9ea8a20011762d03ec24082717dd9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lef=C3=A8vre?= Date: Mon, 14 Nov 2022 02:13:14 +0100 Subject: [PATCH 1/5] feat issue #1341 (Layouts) : support a specifier on %m --- lib/layouts.js | 14 ++++- test/tap/layouts-test.js | 116 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/lib/layouts.js b/lib/layouts.js index 52aef56..2d7c660 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -101,6 +101,8 @@ function dummyLayout(loggingEvent) { * - %c log category * - %h hostname * - %m log data + * - %m{l}, where l is an integer : log data.slice(l) + * - %m{l,u}, where l ans u are integers : log data.slice(l,u) * - %d date in constious formats * - %% % * - %n newline @@ -137,6 +139,8 @@ function patternLayout(pattern, tokens) { const regex = /%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflosCMAF%])(\{([^}]+)\})?|([^%]+)/; + const mSpecifierRegex = /\s*(-?\d)(\s*,\s*(-?\d))?\w*/; + pattern = pattern || TTCC_CONVERSION_PATTERN; function categoryName(loggingEvent, specifier) { @@ -210,8 +214,14 @@ function patternLayout(pattern, tokens) { return os.hostname().toString(); } - function formatMessage(loggingEvent) { - return util.format(...loggingEvent.data); + function formatMessage(loggingEvent, specifier) { + const match = mSpecifierRegex.exec(specifier); + + const lowerBound = match ? parseInt(match[1], 10) : 0; + const upperBound = match && match[3] ? parseInt(match[3], 10) : undefined; + const dataSlice = loggingEvent.data.slice(lowerBound, upperBound); + + return util.format(...dataSlice); } function endOfLine() { diff --git a/test/tap/layouts-test.js b/test/tap/layouts-test.js index e16b83f..a736e5c 100644 --- a/test/tap/layouts-test.js +++ b/test/tap/layouts-test.js @@ -375,6 +375,122 @@ test('log4js layouts', (batch) => { assert.end(); }); + t.test('%m should apply util.format on data', (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m', + "This isn't a test like other ones" + ); + assert.end(); + }); + + t.test( + '%m{P}, with P been an integer, shoud only consider data.slice( P )', + (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{1}', + "isn't test" + ); + assert.end(); + } + ); + + t.test('%m{0, 1} should behave like a dummy layout', (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{0, 1}', + 'This %s a %s like other ones' + ); + assert.end(); + }); + + t.test('%m{1, 2} shoud only consider data.slice( 1, 2 )', (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{1,2}', + "isn't" + ); + assert.end(); + }); + + t.test('%m{1, 2} shoud only consider data.slice( 1, 2 )', (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{1,2}', + "isn't" + ); + assert.end(); + }); + + t.test( + '%m{0, -1} should consider the whole data except the last element', + (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like %s ones', + "isn't", + 'test', + 'other', + "won't be considered in call to util.format", + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{0,-1}', + "This isn't a test like other ones" + ); + assert.end(); + } + ); + t.test('%n should output a new line', (assert) => { testPattern(assert, layout, event, tokens, '%n', EOL); assert.end(); From ab43399200d93f497d820ddcf736087fb32bc53a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lef=C3=A8vre?= Date: Mon, 28 Nov 2022 10:04:25 +0100 Subject: [PATCH 2/5] feat issue #1341 (Layouts) : fix typo & add related doc entry --- docs/layouts.md | 2 ++ lib/layouts.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/layouts.md b/docs/layouts.md index 590b591..7b14f27 100644 --- a/docs/layouts.md +++ b/docs/layouts.md @@ -134,6 +134,8 @@ Fields can be any of: - `%c` log category - `%h` hostname - `%m` log data +- `%m{l}`, where l is an integer, log data.slice(l) +- `%m{l,u}`, where l and u are integers, log data.slice(l,u) - `%d` date, formatted - default is `ISO8601`, format options are: `ISO8601`, `ISO8601_WITH_TZ_OFFSET`, `ABSOLUTETIME`, `DATETIME`, or any string compatible with the [date-format](https://www.npmjs.com/package/date-format) library. e.g. `%d{DATETIME}`, `%d{yyyy/MM/dd-hh.mm.ss}` - `%%` % - for when you want a literal `%` in your output - `%n` newline diff --git a/lib/layouts.js b/lib/layouts.js index 2d7c660..2660a7e 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -102,7 +102,7 @@ function dummyLayout(loggingEvent) { * - %h hostname * - %m log data * - %m{l}, where l is an integer : log data.slice(l) - * - %m{l,u}, where l ans u are integers : log data.slice(l,u) + * - %m{l,u}, where l and u are integers : log data.slice(l,u) * - %d date in constious formats * - %% % * - %n newline From e01c3c7bbf6d434957bbf53ff55950241d259f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lef=C3=A8vre?= Date: Wed, 30 Nov 2022 23:21:46 +0100 Subject: [PATCH 3/5] feat issue #1341 (Layouts) : use split instead of regexp --- lib/layouts.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/layouts.js b/lib/layouts.js index 2660a7e..a969324 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -139,8 +139,6 @@ function patternLayout(pattern, tokens) { const regex = /%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflosCMAF%])(\{([^}]+)\})?|([^%]+)/; - const mSpecifierRegex = /\s*(-?\d)(\s*,\s*(-?\d))?\w*/; - pattern = pattern || TTCC_CONVERSION_PATTERN; function categoryName(loggingEvent, specifier) { @@ -215,12 +213,8 @@ function patternLayout(pattern, tokens) { } function formatMessage(loggingEvent, specifier) { - const match = mSpecifierRegex.exec(specifier); - - const lowerBound = match ? parseInt(match[1], 10) : 0; - const upperBound = match && match[3] ? parseInt(match[3], 10) : undefined; + const [lowerBound, upperBound] = specifier ? specifier.split(',') : []; const dataSlice = loggingEvent.data.slice(lowerBound, upperBound); - return util.format(...dataSlice); } From 0632c2197ec193ca07d52a05946aae114a91e3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lef=C3=A8vre?= Date: Sat, 3 Dec 2022 22:49:28 +0100 Subject: [PATCH 4/5] feat issue #1341 (Layouts) : taking into account code review's feedback --- docs/layouts.md | 4 ++-- lib/layouts.js | 11 +++++---- test/tap/layouts-test.js | 49 +++++++++++++++++++--------------------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/docs/layouts.md b/docs/layouts.md index 7b14f27..1e11e2e 100644 --- a/docs/layouts.md +++ b/docs/layouts.md @@ -134,8 +134,8 @@ Fields can be any of: - `%c` log category - `%h` hostname - `%m` log data -- `%m{l}`, where l is an integer, log data.slice(l) -- `%m{l,u}`, where l and u are integers, log data.slice(l,u) +- `%m{l}` where l is an integer, log data.slice(l) +- `%m{l,u}` where l and u are integers, log data.slice(l, u) - `%d` date, formatted - default is `ISO8601`, format options are: `ISO8601`, `ISO8601_WITH_TZ_OFFSET`, `ABSOLUTETIME`, `DATETIME`, or any string compatible with the [date-format](https://www.npmjs.com/package/date-format) library. e.g. `%d{DATETIME}`, `%d{yyyy/MM/dd-hh.mm.ss}` - `%%` % - for when you want a literal `%` in your output - `%n` newline diff --git a/lib/layouts.js b/lib/layouts.js index a969324..13f0cf1 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -101,8 +101,8 @@ function dummyLayout(loggingEvent) { * - %c log category * - %h hostname * - %m log data - * - %m{l}, where l is an integer : log data.slice(l) - * - %m{l,u}, where l and u are integers : log data.slice(l,u) + * - %m{l} where l is an integer, log data.slice(l) + * - %m{l,u} where l and u are integers, log data.slice(l, u) * - %d date in constious formats * - %% % * - %n newline @@ -213,8 +213,11 @@ function patternLayout(pattern, tokens) { } function formatMessage(loggingEvent, specifier) { - const [lowerBound, upperBound] = specifier ? specifier.split(',') : []; - const dataSlice = loggingEvent.data.slice(lowerBound, upperBound); + let dataSlice = loggingEvent.data; + if (specifier) { + const [lowerBound, upperBound] = specifier.split(','); + dataSlice = dataSlice.slice(lowerBound, upperBound); + } return util.format(...dataSlice); } diff --git a/test/tap/layouts-test.js b/test/tap/layouts-test.js index a736e5c..2375389 100644 --- a/test/tap/layouts-test.js +++ b/test/tap/layouts-test.js @@ -393,28 +393,7 @@ test('log4js layouts', (batch) => { assert.end(); }); - t.test( - '%m{P}, with P been an integer, shoud only consider data.slice( P )', - (assert) => { - const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); - eventWithSeveralDataEntry.data = [ - 'This %s a %s like other ones', - "isn't", - 'test', - ]; - testPattern( - assert, - layout, - eventWithSeveralDataEntry, - tokens, - '%m{1}', - "isn't test" - ); - assert.end(); - } - ); - - t.test('%m{0, 1} should behave like a dummy layout', (assert) => { + t.test('%m{1} should only consider data.slice(1)', (assert) => { const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); eventWithSeveralDataEntry.data = [ 'This %s a %s like other ones', @@ -426,13 +405,31 @@ test('log4js layouts', (batch) => { layout, eventWithSeveralDataEntry, tokens, - '%m{0, 1}', + '%m{1}', + "isn't test" + ); + assert.end(); + }); + + t.test('%m{0,1} should behave like a dummy layout', (assert) => { + const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); + eventWithSeveralDataEntry.data = [ + 'This %s a %s like other ones', + "isn't", + 'test', + ]; + testPattern( + assert, + layout, + eventWithSeveralDataEntry, + tokens, + '%m{0,1}', 'This %s a %s like other ones' ); assert.end(); }); - t.test('%m{1, 2} shoud only consider data.slice( 1, 2 )', (assert) => { + t.test('%m{1,2} should only consider data.slice(1, 2)', (assert) => { const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); eventWithSeveralDataEntry.data = [ 'This %s a %s like other ones', @@ -450,7 +447,7 @@ test('log4js layouts', (batch) => { assert.end(); }); - t.test('%m{1, 2} shoud only consider data.slice( 1, 2 )', (assert) => { + t.test('%m{1,2} should only consider data.slice(1, 2)', (assert) => { const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); eventWithSeveralDataEntry.data = [ 'This %s a %s like other ones', @@ -469,7 +466,7 @@ test('log4js layouts', (batch) => { }); t.test( - '%m{0, -1} should consider the whole data except the last element', + '%m{0,-1} should consider the whole data except the last element', (assert) => { const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); eventWithSeveralDataEntry.data = [ From 5631e2ac229656c059455ba244ac36c001a8fc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Lef=C3=A8vre?= Date: Mon, 5 Dec 2022 12:01:40 +0100 Subject: [PATCH 5/5] feat issue #1341 (Layouts) : removing duplicated test --- test/tap/layouts-test.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/test/tap/layouts-test.js b/test/tap/layouts-test.js index 2375389..3d84278 100644 --- a/test/tap/layouts-test.js +++ b/test/tap/layouts-test.js @@ -447,24 +447,6 @@ test('log4js layouts', (batch) => { assert.end(); }); - t.test('%m{1,2} should only consider data.slice(1, 2)', (assert) => { - const eventWithSeveralDataEntry = JSON.parse(JSON.stringify(event)); - eventWithSeveralDataEntry.data = [ - 'This %s a %s like other ones', - "isn't", - 'test', - ]; - testPattern( - assert, - layout, - eventWithSeveralDataEntry, - tokens, - '%m{1,2}', - "isn't" - ); - assert.end(); - }); - t.test( '%m{0,-1} should consider the whole data except the last element', (assert) => {