diff --git a/docs/layouts.md b/docs/layouts.md index 590b591..1e11e2e 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 52aef56..13f0cf1 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 and u are integers, log data.slice(l, u) * - %d date in constious formats * - %% % * - %n newline @@ -210,8 +212,13 @@ function patternLayout(pattern, tokens) { return os.hostname().toString(); } - function formatMessage(loggingEvent) { - return util.format(...loggingEvent.data); + function formatMessage(loggingEvent, specifier) { + let dataSlice = loggingEvent.data; + if (specifier) { + const [lowerBound, upperBound] = specifier.split(','); + dataSlice = dataSlice.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..3d84278 100644 --- a/test/tap/layouts-test.js +++ b/test/tap/layouts-test.js @@ -375,6 +375,101 @@ 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{1} should only consider data.slice(1)', (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} 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) => { + 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();