diff --git a/Readme.md b/Readme.md index 99b5cd3d..2a868494 100644 --- a/Readme.md +++ b/Readme.md @@ -77,6 +77,7 @@ node app.js | pino-pretty - `--minimumLevel` (`-L`): Hide messages below the specified log level. Accepts a number, `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. If any more filtering is required, consider using [`jq`](https://stedolan.github.io/jq/). - `--customLevels` (`-x`): Override default levels with custom levels, e.g. `-x err:99,info:1` - `--customColors` (`-X`): Override default colors with custom colors, e.g. `-X err:red,info:blue` +- `--colorizeMessage` (`-z`): Applies the level label color to the entire message output - `--useOnlyCustomProps` (`-U`): Only use custom levels and colors (if provided) (default: true); else fallback to default levels and colors, e.g. `-U false` - `--messageFormat` (`-o`): Format output of message, e.g. `{levelLabel} - {pid} - url:{req.url}` will output message: `INFO - 1123 - url:localhost:3000/test` Default: `false` @@ -267,6 +268,7 @@ The options accepted have keys corresponding to the options described in [CLI Ar singleLine: false, // --singleLine customColors: 'err:red,info:blue', // --customColors customLevels: 'err:99,info:1', // --customLevels (not required with pino >=8.21.0) + colorizeMessage: false, // --colorizeMessage levelLabel: 'levelLabel', // --levelLabel minimumLevel: 'info', // --minimumLevel useOnlyCustomProps: true, // --useOnlyCustomProps diff --git a/bin.js b/bin.js old mode 100644 new mode 100755 index 4a7a5f73..247f3d9b --- a/bin.js +++ b/bin.js @@ -60,7 +60,8 @@ if (cmd.h || cmd.help) { ignore: 'i', include: 'I', hideObject: 'H', - singleLine: 'S' + singleLine: 'S', + colorizeMessage: 'z' }, default: { messageKey: DEFAULT_VALUE, diff --git a/index.d.ts b/index.d.ts index 7339d534..a62bfc84 100644 --- a/index.d.ts +++ b/index.d.ts @@ -214,6 +214,12 @@ declare namespace PinoPretty { * @default true */ useOnlyCustomProps?: boolean; + /** + * Print the message same color of the level. + * + * @default false + */ + colorizeMessage?: boolean; } function build(options: PrettyOptions): PrettyStream; diff --git a/index.js b/index.js index fcda6b2f..698390be 100644 --- a/index.js +++ b/index.js @@ -70,6 +70,8 @@ const pretty = require('./lib/pretty') * it must be a format string. * @property {boolean} [useOnlyCustomProps=true] When true, only custom levels * and colors will be used if they have been provided. + * @property {boolean} [colorizeMessage=false] When true, the message will + * get the same color of the level */ /** @@ -99,7 +101,8 @@ const defaultOptions = { singleLine: false, timestampKey: TIMESTAMP_KEY, translateTime: true, - useOnlyCustomProps: true + useOnlyCustomProps: true, + colorizeMessage: false } /** diff --git a/lib/colors.js b/lib/colors.js index 321b7b7e..60e987f4 100644 --- a/lib/colors.js +++ b/lib/colors.js @@ -59,6 +59,7 @@ function plainColorizer (useOnlyCustomProps) { customColoredColorizer.message = plain.message customColoredColorizer.greyMessage = plain.greyMessage customColoredColorizer.property = plain.property + customColoredColorizer.levelColors = plain customColoredColorizer.colors = createColors({ useColor: false }) return customColoredColorizer } @@ -71,6 +72,7 @@ function coloredColorizer (useOnlyCustomProps) { customColoredColorizer.message = colored.message customColoredColorizer.property = colored.property customColoredColorizer.greyMessage = colored.greyMessage + customColoredColorizer.levelColors = colored customColoredColorizer.colors = availableColors return customColoredColorizer } @@ -86,6 +88,7 @@ function customColoredColorizerFactory (customColors, useOnlyCustomProps) { customColoredColorizer.colors = availableColors customColoredColorizer.message = customColoredColorizer.message || customColored.message customColoredColorizer.greyMessage = customColoredColorizer.greyMessage || customColored.greyMessage + customColoredColorizer.levelColors = customColored || colored return customColoredColorizer } diff --git a/lib/utils/parse-factory-options.js b/lib/utils/parse-factory-options.js index 3b051f03..040945a0 100644 --- a/lib/utils/parse-factory-options.js +++ b/lib/utils/parse-factory-options.js @@ -78,7 +78,8 @@ function parseFactoryOptions (options) { minimumLevel, singleLine, timestampKey, - translateTime + translateTime, + colorizeMessage } = options const errorProps = options.errorProps.split(',') const useOnlyCustomProps = typeof options.useOnlyCustomProps === 'boolean' @@ -168,6 +169,7 @@ function parseFactoryOptions (options) { singleLine, timestampKey, translateTime, - useOnlyCustomProps + useOnlyCustomProps, + colorizeMessage } } diff --git a/lib/utils/prettify-message.js b/lib/utils/prettify-message.js index ee2f3dc8..d43b8092 100644 --- a/lib/utils/prettify-message.js +++ b/lib/utils/prettify-message.js @@ -33,8 +33,10 @@ function prettifyMessage ({ log, context }) { levelLabel, messageFormat, messageKey, - useOnlyCustomProps + useOnlyCustomProps, + colorizeMessage } = context + if (messageFormat && typeof messageFormat === 'string') { const parsedMessageFormat = interpretConditionals(messageFormat, log) @@ -51,13 +53,28 @@ function prettifyMessage ({ log, context }) { // Parse nested key access, e.g. `{keyA.subKeyB}`. return getPropertyValue(log, p1) || '' }) + + if (colorizeMessage) { + return colorizer.levelColors[getPropertyValue(log, levelKey)](message) + } + return colorizer.message(message) } if (messageFormat && typeof messageFormat === 'function') { const msg = messageFormat(log, messageKey, levelLabel, { colors: colorizer.colors }) + + if (colorizeMessage) { + return colorizer.levelColors[getPropertyValue(log, levelKey)](msg) + } + return colorizer.message(msg) } if (messageKey in log === false) return undefined if (typeof log[messageKey] !== 'string' && typeof log[messageKey] !== 'number' && typeof log[messageKey] !== 'boolean') return undefined + + if (colorizeMessage) { + return colorizer.levelColors[getPropertyValue(log, levelKey)](log[messageKey]) + } + return colorizer.message(log[messageKey]) } diff --git a/lib/utils/prettify-message.test.js b/lib/utils/prettify-message.test.js index ecb3eb77..2de3572f 100644 --- a/lib/utils/prettify-message.test.js +++ b/lib/utils/prettify-message.test.js @@ -87,6 +87,34 @@ test('returns message formatted by `messageFormat` option - levelLabel & useOnly t.assert.strictEqual(str, '[30] INFO appModule - foo') }) +test('returns a default(cyan) colored message when `colorizeMessage` is false', t => { + const colorizer = getColorizer(true) + + const str = prettifyMessage({ + log: { msg: 'foo', level: 40 }, + context: { + ...context, + colorizer, + colorizeMessage: false + } + }) + t.assert.strictEqual(str, '\x1B[36mfoo\x1B[39m') +}) + +test('returns a colored(yellow warning) message when `colorizeMessage` is true', t => { + const colorizer = getColorizer(true) + + const str = prettifyMessage({ + log: { msg: 'foo', level: 40 }, + context: { + ...context, + colorizer, + colorizeMessage: true + } + }) + t.assert.strictEqual(str, '\x1B[33mfoo\x1B[39m') +}) + test('returns message formatted by `messageFormat` option - levelLabel & useOnlyCustomProps true', t => { const str = prettifyMessage({ log: { msg: 'foo', context: 'appModule', level: 30 }, diff --git a/test/cli.test.js b/test/cli.test.js index 7055a927..2d6cb3c3 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -162,6 +162,20 @@ describe('cli', () => { }) } + for (const optionName of ['--colorizeMessage', '-z']) { + test(`colorize messages via ${optionName}`, async (t) => { + t.plan(1) + const child = spawn(process.argv[0], [bin, optionName], { env }) + child.on('error', t.assert.fail) + const endPromise = once(child.stdout, 'data', (data) => { + t.assert.strictEqual(data.toString(), `[${formattedEpoch}] INFO (42): hello world\n`) + }) + child.stdin.write(logLine) + await endPromise + t.after(() => child.kill()) + }) + } + for (const optionName of ['--useOnlyCustomProps', '-U']) { test(`customize levels via ${optionName} false and customColors`, async (t) => { t.plan(1) diff --git a/test/types/pino-pretty.test-d.ts b/test/types/pino-pretty.test-d.ts index 8649edc3..cfb602bc 100644 --- a/test/types/pino-pretty.test-d.ts +++ b/test/types/pino-pretty.test-d.ts @@ -47,6 +47,7 @@ const options: PinoPretty.PrettyOptions = { append: true, mkdir: true, useOnlyCustomProps: false, + colorizeMessage: false, }; expectType(pretty()); // #326