pino-pretty
Advanced tools
Comparing version 10.3.1 to 11.0.0
@@ -1,2 +0,2 @@ | ||
Usage: pino pretty [options] [command] | ||
Usage: pino-pretty [options] [command] | ||
@@ -3,0 +3,0 @@ Commands: |
@@ -13,2 +13,4 @@ // Type definitions for pino-pretty 7.0 | ||
import { DestinationStream, Level } from 'pino'; | ||
import LevelPrettifierExtras = PinoPretty.LevelPrettifierExtras; | ||
import * as Colorette from "colorette"; | ||
@@ -183,3 +185,6 @@ type LogDescriptor = Record<string, unknown>; | ||
*/ | ||
customPrettifiers?: Record<string, PinoPretty.Prettifier>; | ||
customPrettifiers?: Record<string, PinoPretty.Prettifier> & | ||
{ | ||
level?: PinoPretty.Prettifier<PinoPretty.LevelPrettifierExtras> | ||
}; | ||
/** | ||
@@ -209,4 +214,6 @@ * Change the level names and values to an user custom preset. | ||
declare namespace PinoPretty { | ||
type Prettifier = (inputData: string | object) => string; | ||
type MessageFormatFunc = (log: LogDescriptor, messageKey: string, levelLabel: string) => string; | ||
type Prettifier<T = object> = (inputData: string | object, key: string, log: object, extras: PrettifierExtras<T>) => string; | ||
type PrettifierExtras<T = object> = {colors: Colorette.Colorette} & T; | ||
type LevelPrettifierExtras = {label: string, labelColorized: string} | ||
type MessageFormatFunc = (log: LogDescriptor, messageKey: string, levelLabel: string, extras: PrettifierExtras) => string; | ||
type PrettyOptions = PrettyOptions_; | ||
@@ -213,0 +220,0 @@ type PrettyStream = Transform & OnUnknown; |
'use strict' | ||
const { LEVELS, LEVEL_NAMES } = require('./constants') | ||
const nocolor = input => input | ||
@@ -19,2 +17,3 @@ const plain = { | ||
const { createColors } = require('colorette') | ||
const getLevelLabelData = require('./utils/get-level-label-data') | ||
const availableColors = createColors({ useColor: true }) | ||
@@ -48,14 +47,4 @@ const { white, bgRed, red, yellow, green, blue, gray, cyan } = availableColors | ||
return function (level, colorizer, { customLevels, customLevelNames } = {}) { | ||
const levels = useOnlyCustomProps ? customLevels || LEVELS : Object.assign({}, LEVELS, customLevels) | ||
const levelNames = useOnlyCustomProps ? customLevelNames || LEVEL_NAMES : Object.assign({}, LEVEL_NAMES, customLevelNames) | ||
const [levelStr, levelNum] = getLevelLabelData(useOnlyCustomProps, customLevels, customLevelNames)(level) | ||
let levelNum = 'default' | ||
if (Number.isInteger(+level)) { | ||
levelNum = Object.prototype.hasOwnProperty.call(levels, level) ? level : levelNum | ||
} else { | ||
levelNum = Object.prototype.hasOwnProperty.call(levelNames, level.toLowerCase()) ? levelNames[level.toLowerCase()] : levelNum | ||
} | ||
const levelStr = levels[levelNum] | ||
return Object.prototype.hasOwnProperty.call(colorizer, levelNum) ? colorizer[levelNum](levelStr) : colorizer.default(levelStr) | ||
@@ -72,2 +61,3 @@ } | ||
customColoredColorizer.greyMessage = plain.greyMessage | ||
customColoredColorizer.colors = createColors({ useColor: false }) | ||
return customColoredColorizer | ||
@@ -83,2 +73,3 @@ } | ||
customColoredColorizer.greyMessage = colored.greyMessage | ||
customColoredColorizer.colors = availableColors | ||
return customColoredColorizer | ||
@@ -95,2 +86,3 @@ } | ||
} | ||
customColoredColorizer.colors = availableColors | ||
customColoredColorizer.message = customColoredColorizer.message || customColored.message | ||
@@ -113,2 +105,3 @@ customColoredColorizer.greyMessage = customColoredColorizer.greyMessage || customColored.greyMessage | ||
* colorized to a predefined color. | ||
* @property {Colorette.Colorette} colors Available color functions based on `useColor` (or `colorize`) context | ||
*/ | ||
@@ -115,0 +108,0 @@ |
@@ -25,3 +25,4 @@ 'use strict' | ||
prettifyTime: require('./prettify-time.js'), | ||
splitPropertyKey: require('./split-property-key.js') | ||
splitPropertyKey: require('./split-property-key.js'), | ||
getLevelLabelData: require('./get-level-label-data') | ||
} | ||
@@ -83,2 +84,8 @@ | ||
/** | ||
* @typedef {object} PrettifyMessageExtras | ||
* @property {object} colors Available color functions based on `useColor` (or `colorize`) context | ||
* the options. | ||
*/ | ||
/** | ||
* A function that accepts a log object, name of the message key, and name of | ||
@@ -95,2 +102,3 @@ * the level label key and returns a formatted log line. | ||
* contains the log level name. | ||
* @param {PrettifyMessageExtras} extras Additional data available for message context | ||
* @returns {string} | ||
@@ -97,0 +105,0 @@ * |
@@ -11,2 +11,3 @@ 'use strict' | ||
const handleCustomLevelsNamesOpts = require('./handle-custom-levels-names-opts') | ||
const handleLevelLabelData = require('./get-level-label-data') | ||
@@ -36,2 +37,3 @@ /** | ||
* included in the output. | ||
* @property {function} getLevelLabelData Pass a numeric level to return [levelLabelString,levelNum] | ||
* @property {boolean} hideObject Indicates the prettifier should omit objects | ||
@@ -89,22 +91,39 @@ * in the output. | ||
const customLevelNames = handleCustomLevelsNamesOpts(options.customLevels) | ||
const getLevelLabelData = handleLevelLabelData(useOnlyCustomProps, customLevels, customLevelNames) | ||
let customColors | ||
if (options.customColors) { | ||
customColors = options.customColors.split(',').reduce((agg, value) => { | ||
const [level, color] = value.split(':') | ||
const condition = useOnlyCustomProps | ||
? options.customLevels | ||
: customLevelNames[level] !== undefined | ||
const levelNum = condition | ||
? customLevelNames[level] | ||
: LEVEL_NAMES[level] | ||
const colorIdx = levelNum !== undefined | ||
? levelNum | ||
: level | ||
agg.push([colorIdx, color]) | ||
return agg | ||
}, []) | ||
if (typeof options.customColors === 'string') { | ||
customColors = options.customColors.split(',').reduce((agg, value) => { | ||
const [level, color] = value.split(':') | ||
const condition = useOnlyCustomProps | ||
? options.customLevels | ||
: customLevelNames[level] !== undefined | ||
const levelNum = condition | ||
? customLevelNames[level] | ||
: LEVEL_NAMES[level] | ||
const colorIdx = levelNum !== undefined | ||
? levelNum | ||
: level | ||
agg.push([colorIdx, color]) | ||
return agg | ||
}, []) | ||
} else if (typeof options.customColors === 'object') { | ||
customColors = Object.keys(options.customColors).reduce((agg, value) => { | ||
const [level, color] = [value, options.customColors[value]] | ||
const condition = useOnlyCustomProps | ||
? options.customLevels | ||
: customLevelNames[level] !== undefined | ||
const levelNum = condition | ||
? customLevelNames[level] | ||
: LEVEL_NAMES[level] | ||
const colorIdx = levelNum !== undefined | ||
? levelNum | ||
: level | ||
agg.push([colorIdx, color]) | ||
return agg | ||
}, []) | ||
} else { | ||
throw new Error('options.customColors must be of type string or object.') | ||
} | ||
} | ||
@@ -141,2 +160,3 @@ | ||
errorProps, | ||
getLevelLabelData, | ||
hideObject, | ||
@@ -143,0 +163,0 @@ ignoreKeys, |
@@ -29,3 +29,4 @@ 'use strict' | ||
customLevelNames, | ||
levelKey | ||
levelKey, | ||
getLevelLabelData | ||
} = context | ||
@@ -35,3 +36,8 @@ const prettifier = context.customPrettifiers?.level | ||
if (output === undefined) return undefined | ||
return prettifier ? prettifier(output) : colorizer(output, { customLevels, customLevelNames }) | ||
const labelColorized = colorizer(output, { customLevels, customLevelNames }) | ||
if (prettifier) { | ||
const [label] = getLevelLabelData(output) | ||
return prettifier(output, levelKey, log, { label, labelColorized, colors: colorizer.colors }) | ||
} | ||
return labelColorized | ||
} |
@@ -6,2 +6,3 @@ 'use strict' | ||
const getColorizer = require('../colors') | ||
const getLevelLabelData = require('./get-level-label-data') | ||
const { | ||
@@ -16,3 +17,4 @@ LEVEL_KEY | ||
levelKey: LEVEL_KEY, | ||
customPrettifiers: undefined | ||
customPrettifiers: undefined, | ||
getLevelLabelData: getLevelLabelData(false, {}, {}) | ||
} | ||
@@ -19,0 +21,0 @@ |
@@ -57,3 +57,3 @@ 'use strict' | ||
if (messageFormat && typeof messageFormat === 'function') { | ||
const msg = messageFormat(log, messageKey, levelLabel) | ||
const msg = messageFormat(log, messageKey, levelLabel, { colors: colorizer.colors }) | ||
return colorizer.message(msg) | ||
@@ -60,0 +60,0 @@ } |
@@ -188,1 +188,52 @@ 'use strict' | ||
}) | ||
tap.test('`messageFormat` supports function definition with colorizer object', async t => { | ||
const colorizer = getColorizer(true) | ||
const str = prettifyMessage({ | ||
log: { level: 30, request: { url: 'localhost/test' }, msg: 'incoming request' }, | ||
context: { | ||
...context, | ||
colorizer, | ||
messageFormat: (log, messageKey, levelLabel, { colors }) => { | ||
let msg = log[messageKey] | ||
if (msg === 'incoming request') msg = `--> ${colors.red(log.request.url)}` | ||
return msg | ||
} | ||
} | ||
}) | ||
t.equal(str, '\u001B[36m--> \u001B[31mlocalhost/test\u001B[36m\u001B[39m') | ||
}) | ||
tap.test('`messageFormat` supports function definition with colorizer object when using custom colors', async t => { | ||
const colorizer = getColorizer(true, [[30, 'brightGreen']], false) | ||
const str = prettifyMessage({ | ||
log: { level: 30, request: { url: 'localhost/test' }, msg: 'incoming request' }, | ||
context: { | ||
...context, | ||
colorizer, | ||
messageFormat: (log, messageKey, levelLabel, { colors }) => { | ||
let msg = log[messageKey] | ||
if (msg === 'incoming request') msg = `--> ${colors.red(log.request.url)}` | ||
return msg | ||
} | ||
} | ||
}) | ||
t.equal(str, '\u001B[36m--> \u001B[31mlocalhost/test\u001B[36m\u001B[39m') | ||
}) | ||
tap.test('`messageFormat` supports function definition with colorizer object when no color is supported', async t => { | ||
const colorizer = getColorizer(false) | ||
const str = prettifyMessage({ | ||
log: { level: 30, request: { url: 'localhost/test' }, msg: 'incoming request' }, | ||
context: { | ||
...context, | ||
colorizer, | ||
messageFormat: (log, messageKey, levelLabel, { colors }) => { | ||
let msg = log[messageKey] | ||
if (msg === 'incoming request') msg = `--> ${colors.red(log.request.url)}` | ||
return msg | ||
} | ||
} | ||
}) | ||
t.equal(str, '--> localhost/test') | ||
}) |
@@ -46,3 +46,4 @@ 'use strict' | ||
objectColorizer, | ||
singleLine | ||
singleLine, | ||
colorizer | ||
} = context | ||
@@ -61,3 +62,3 @@ const keysToIgnore = [].concat(skipKeys) | ||
const pretty = typeof customPrettifiers[k] === 'function' | ||
? customPrettifiers[k](v, k, log) | ||
? customPrettifiers[k](v, k, log, { colors: colorizer.colors }) | ||
: v | ||
@@ -64,0 +65,0 @@ if (errorLikeKeys.includes(k)) { |
@@ -9,2 +9,3 @@ 'use strict' | ||
} = require('../constants') | ||
const getColorizer = require('../colors') | ||
@@ -17,3 +18,4 @@ const context = { | ||
objectColorizer: colors(), | ||
singleLine: false | ||
singleLine: false, | ||
colorizer: getColorizer() | ||
} | ||
@@ -20,0 +22,0 @@ |
{ | ||
"name": "pino-pretty", | ||
"version": "10.3.1", | ||
"version": "11.0.0", | ||
"description": "Prettifier for Pino log lines", | ||
@@ -5,0 +5,0 @@ "type": "commonjs", |
@@ -300,5 +300,20 @@ <a id="intro"></a> | ||
All prettifiers use this function signature: | ||
```js | ||
['logObjKey']: (output, keyName, logObj, extras) => string | ||
``` | ||
* `logObjKey` - name of the key of the property in the log object that should have this function applied to it | ||
* `output` - the value of the property in the log object | ||
* `keyName` - the name of the property (useful for `level` and `message` when `levelKey` or `messageKey` is used) | ||
* `logObj` - the full log object, for context | ||
* `extras` - an object containing **additional** data/functions created in the context of this pino-pretty logger or specific to the key (see `level` prettifying below) | ||
* All `extras` objects contain `colors` which is a [Colorette](https://github.com/jorgebucaran/colorette?tab=readme-ov-file#supported-colors) object containing color functions. Colors are enabled based on `colorize` provided to pino-pretty or `colorette.isColorSupported` if `colorize` was not provided. | ||
Additionally, `customPrettifiers` can be used to format the `time`, `hostname`, | ||
`pid`, `name`, `caller` and `level` outputs: | ||
`pid`, `name`, `caller` and `level` outputs AS WELL AS any arbitrary key-value that exists on a given log object. | ||
An example usage of `customPrettifiers` using all parameters from the function signature: | ||
```js | ||
@@ -315,8 +330,13 @@ { | ||
level: logLevel => `LEVEL: ${logLevel}`, | ||
// level provides additional data in `extras`: | ||
// * label => derived level label string | ||
// * labelColorized => derived level label string with colorette colors applied based on customColors and whether colors are supported | ||
level: (logLevel, key, log, { label, labelColorized, colors }) => `LEVEL: ${logLevel} LABEL: ${levelLabel} COLORIZED LABEL: ${labelColorized}`, | ||
// other prettifiers can be used for the other keys if needed, for example | ||
hostname: hostname => colorGreen(hostname), | ||
pid: pid => colorRed(pid), | ||
name: name => colorBlue(name), | ||
caller: caller => colorCyan(caller) | ||
hostname: hostname => `MY HOST: ${hostname}`, | ||
pid: pid => pid, | ||
name: (name, key, log, { colors }) => `${colors.blue(name)}`, | ||
caller: (caller, key, log, { colors }) => `${colors.greenBright(caller)}`, | ||
myCustomLogProp: (value, key, log, { colors }) => `My Prop -> ${colors.bold(value)} <--` | ||
} | ||
@@ -326,15 +346,2 @@ } | ||
Note that prettifiers do not include any coloring, if the stock coloring on | ||
`level` is desired, it can be accomplished using the following: | ||
```js | ||
const { colorizerFactory } = require('pino-pretty') | ||
const levelColorize = colorizerFactory(true) | ||
const levelPrettifier = logLevel => `LEVEL: ${levelColorize(logLevel)}` | ||
//... | ||
{ | ||
customPrettifiers: { level: levelPrettifier } | ||
} | ||
``` | ||
`messageFormat` option allows you to customize the message output. | ||
@@ -358,9 +365,11 @@ A template `string` like this can define the format: | ||
This option can also be defined as a `function` with this prototype: | ||
This option can also be defined as a `function` with this function signature: | ||
```js | ||
{ | ||
messageFormat: (log, messageKey, levelLabel) => { | ||
messageFormat: (log, messageKey, levelLabel, { colors }) => { | ||
// do some log message customization | ||
return customized_message; | ||
// | ||
// `colors` is a Colorette object with colors enabled based on `colorize` option | ||
return `This is a ${color.red('colorized')}, custom message: ${log[messageKey]}`; | ||
} | ||
@@ -367,0 +376,0 @@ } |
@@ -259,2 +259,44 @@ 'use strict' | ||
t.test('can use a customPrettifier to get final level label (no color)', (t) => { | ||
t.plan(1) | ||
const customPrettifiers = { | ||
level: (level, key, logThis, { label }) => { | ||
return `LEVEL: ${label}` | ||
} | ||
} | ||
const pretty = prettyFactory({ customPrettifiers, colorize: false, useOnlyCustomProps: false }) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
t.equal( | ||
formatted, | ||
`[${formattedEpoch}] LEVEL: INFO (${pid}): foo\n` | ||
) | ||
cb() | ||
} | ||
})) | ||
log.info({ msg: 'foo' }) | ||
}) | ||
t.test('can use a customPrettifier to get final level label (colorized)', (t) => { | ||
t.plan(1) | ||
const customPrettifiers = { | ||
level: (level, key, logThis, { label, labelColorized }) => { | ||
return `LEVEL: ${labelColorized}` | ||
} | ||
} | ||
const pretty = prettyFactory({ customPrettifiers, colorize: true, useOnlyCustomProps: false }) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
t.equal( | ||
formatted, | ||
`[${formattedEpoch}] LEVEL: [32mINFO[39m (${pid}): [36mfoo[39m\n` | ||
) | ||
cb() | ||
} | ||
})) | ||
log.info({ msg: 'foo' }) | ||
}) | ||
t.test('can use a customPrettifier on name output', (t) => { | ||
@@ -1065,2 +1107,28 @@ t.plan(1) | ||
t.test('support custom colors object', async (t) => { | ||
t.plan(1) | ||
const pretty = prettyFactory({ | ||
colorize: true, | ||
customColors: { | ||
trace: 'cyan', | ||
debug: 'blue', | ||
info: 'green', | ||
warn: 'yellow', | ||
error: 'red', | ||
fatal: 'red' | ||
} | ||
}) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
t.equal( | ||
formatted, | ||
`[${formattedEpoch}] \u001B[32mINFO\u001B[39m (${pid}): \u001B[36mfoo\u001B[39m\n` | ||
) | ||
cb() | ||
} | ||
})) | ||
log.info('foo') | ||
}) | ||
t.end() | ||
@@ -1067,0 +1135,0 @@ }) |
@@ -35,2 +35,5 @@ import { expectType } from "tsd"; | ||
return value.toString().toUpperCase(); | ||
}, | ||
level: (level, label, colorized) => { | ||
return level.toString(); | ||
} | ||
@@ -37,0 +40,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
228089
74
5590
390