Skip to content

Commit 4f992c2

Browse files
feat: automatically consume pino config when using pino@>=8.21.0 (#508)
1 parent 2596a6b commit 4f992c2

File tree

7 files changed

+148
-21
lines changed

7 files changed

+148
-21
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ jobs:
4040
contents: read
4141
strategy:
4242
matrix:
43-
node-version: [14, 16, 18]
43+
node-version: [14, 16, 18, 20]
4444
os: [ubuntu-latest]
45+
pino-version: [8.20.0, ^8.21.0, ^9.0.0]
46+
exclude:
47+
- node-version: 14
48+
pino-version: ^9.0.0
49+
- node-version: 16
50+
pino-version: ^9.0.0
4551
steps:
4652
- name: Check out repo
4753
uses: actions/checkout@v4
@@ -62,6 +68,9 @@ jobs:
6268
- name: Install dependencies
6369
run: npm i --ignore-scripts
6470

71+
- name: Install pino ${{ matrix.pino-version }}
72+
run: npm i --no-save pino@${{ matrix.pino-version }}
73+
6574
- name: Run tests
6675
run: npm run ci
6776

Readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,10 @@ The options accepted have keys corresponding to the options described in [CLI Ar
240240
colorize: colorette.isColorSupported, // --colorize
241241
colorizeObjects: true, //--colorizeObjects
242242
crlf: false, // --crlf
243-
errorLikeObjectKeys: ['err', 'error'], // --errorLikeObjectKeys
243+
errorLikeObjectKeys: ['err', 'error'], // --errorLikeObjectKeys (not required to match custom errorKey with pino >=8.21.0)
244244
errorProps: '', // --errorProps
245245
levelFirst: false, // --levelFirst
246-
messageKey: 'msg', // --messageKey
246+
messageKey: 'msg', // --messageKey (not required with pino >=8.21.0)
247247
levelKey: 'level', // --levelKey
248248
messageFormat: false, // --messageFormat
249249
timestampKey: 'time', // --timestampKey
@@ -253,7 +253,7 @@ The options accepted have keys corresponding to the options described in [CLI Ar
253253
hideObject: false, // --hideObject
254254
singleLine: false, // --singleLine
255255
customColors: 'err:red,info:blue', // --customColors
256-
customLevels: 'err:99,info:1', // --customLevels
256+
customLevels: 'err:99,info:1', // --customLevels (not required with pino >=8.21.0)
257257
levelLabel: 'levelLabel', // --levelLabel
258258
minimumLevel: 'info', // --minimumLevel
259259
useOnlyCustomProps: true, // --useOnlyCustomProps

index.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ interface PrettyOptions_ {
7171
/**
7272
* The key in the JSON object to use as the highlighted message.
7373
* @default "msg"
74+
*
75+
* Not required when used with pino >= 8.21.0
7476
*/
7577
messageKey?: string;
7678
/**
@@ -122,6 +124,8 @@ interface PrettyOptions_ {
122124
/**
123125
* Define the log keys that are associated with error like objects.
124126
* @default ["err", "error"]
127+
*
128+
* Not required to handle custom errorKey when used with pino >= 8.21.0
125129
*/
126130
errorLikeObjectKeys?: string[];
127131
/**
@@ -192,6 +196,8 @@ interface PrettyOptions_ {
192196
*
193197
* @example ( CSV ) customLevels: 'info:10,some_level:40'
194198
* @example ( Object ) customLevels: { info: 10, some_level: 40 }
199+
*
200+
* Not required when used with pino >= 8.21.0
195201
*/
196202
customLevels?: string|object;
197203
/**

index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,18 @@ function prettyFactory (options) {
131131
* @returns {Transform | (Transform & OnUnknown)}
132132
*/
133133
function build (opts = {}) {
134-
const pretty = prettyFactory(opts)
134+
let pretty = prettyFactory(opts)
135135
return abstractTransport(function (source) {
136+
source.on('message', function pinoConfigListener (message) {
137+
if (!message || message.code !== 'PINO_CONFIG') return
138+
Object.assign(opts, {
139+
messageKey: message.config.messageKey,
140+
errorLikeObjectKeys: Array.from(new Set([...(opts.errorLikeObjectKeys || ERROR_LIKE_KEYS), message.config.errorKey])),
141+
customLevels: message.config.levels.values
142+
})
143+
pretty = prettyFactory(opts)
144+
source.off('message', pinoConfigListener)
145+
})
136146
const stream = new Transform({
137147
objectMode: true,
138148
autoDestroy: true,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"pino": "^9.0.0",
5656
"pre-commit": "^1.2.2",
5757
"rimraf": "^3.0.2",
58+
"semver": "^7.6.0",
5859
"snazzy": "^9.0.0",
5960
"standard": "^17.0.0",
6061
"tap": "^16.0.0",

test/basic.test.js

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const path = require('path')
1111
const rimraf = require('rimraf')
1212
const { join } = require('path')
1313
const fs = require('fs')
14+
const semver = require('semver')
1415
const pinoPretty = require('..')
1516
const SonicBoom = require('sonic-boom')
1617
const _prettyFactory = pinoPretty.prettyFactory
@@ -1074,7 +1075,7 @@ test('basic prettifier tests', (t) => {
10741075
t.test('stream usage', async (t) => {
10751076
t.plan(1)
10761077
const tmpDir = path.join(__dirname, '.tmp_' + Date.now())
1077-
t.teardown(() => rimraf(tmpDir, noop))
1078+
t.teardown(() => rimraf.sync(tmpDir))
10781079

10791080
const destination = join(tmpDir, 'output')
10801081

@@ -1102,24 +1103,28 @@ test('basic prettifier tests', (t) => {
11021103
t.test('sync option', async (t) => {
11031104
t.plan(1)
11041105
const tmpDir = path.join(__dirname, '.tmp_' + Date.now())
1105-
t.teardown(() => rimraf(tmpDir, noop))
1106+
t.teardown(() => rimraf.sync(tmpDir))
11061107

11071108
const destination = join(tmpDir, 'output')
11081109

1109-
const pretty = pinoPretty({
1110-
singleLine: true,
1111-
colorize: false,
1112-
mkdir: true,
1113-
append: false,
1114-
sync: true,
1115-
destination
1116-
})
1117-
const log = pino(pretty)
1118-
log.info({ msg: 'message', extra: { foo: 'bar', number: 42 }, upper: 'foobar' })
1110+
const log = pino(pino.transport({
1111+
target: '..',
1112+
options: {
1113+
singleLine: true,
1114+
colorize: false,
1115+
mkdir: true,
1116+
append: false,
1117+
sync: true,
1118+
destination
1119+
}
1120+
}))
1121+
log.info({ msg: 'message', extra: { foo: 'bar', number: 43 }, upper: 'foobar' })
1122+
1123+
await watchFileCreated(destination)
11191124

11201125
const formatted = fs.readFileSync(destination, 'utf8')
11211126

1122-
t.equal(formatted, `[${formattedEpoch}] INFO (${pid}): message {"extra":{"foo":"bar","number":42},"upper":"foobar"}\n`)
1127+
t.equal(formatted, `[${formattedEpoch}] INFO (${pid}): message {"extra":{"foo":"bar","number":43},"upper":"foobar"}\n`)
11231128
})
11241129

11251130
t.test('support custom colors object', async (t) => {
@@ -1151,6 +1156,59 @@ test('basic prettifier tests', (t) => {
11511156
t.end()
11521157
})
11531158

1159+
if (semver.gte(pino.version, '8.21.0')) {
1160+
test('using pino config', (t) => {
1161+
t.beforeEach(() => {
1162+
Date.originalNow = Date.now
1163+
Date.now = () => epoch
1164+
})
1165+
t.afterEach(() => {
1166+
Date.now = Date.originalNow
1167+
delete Date.originalNow
1168+
})
1169+
1170+
t.test('can use different message keys', (t) => {
1171+
t.plan(1)
1172+
const destination = new Writable({
1173+
write (formatted, enc, cb) {
1174+
t.equal(
1175+
formatted.toString(),
1176+
`[${formattedEpoch}] INFO (${pid}): baz\n`
1177+
)
1178+
cb()
1179+
}
1180+
})
1181+
const pretty = pinoPretty({
1182+
destination,
1183+
colorize: false
1184+
})
1185+
const log = pino({ messageKey: 'bar' }, pretty)
1186+
log.info({ bar: 'baz' })
1187+
})
1188+
1189+
t.test('handles customLogLevels', (t) => {
1190+
t.plan(1)
1191+
const destination = new Writable({
1192+
write (formatted, enc, cb) {
1193+
t.equal(
1194+
formatted.toString(),
1195+
`[${formattedEpoch}] TESTCUSTOM (${pid}): test message\n`
1196+
)
1197+
cb()
1198+
}
1199+
})
1200+
const pretty = pinoPretty({
1201+
destination,
1202+
colorize: false
1203+
})
1204+
const log = pino({ customLevels: { testCustom: 35 } }, pretty)
1205+
log.testCustom('test message')
1206+
})
1207+
1208+
t.end()
1209+
})
1210+
}
1211+
11541212
function watchFileCreated (filename) {
11551213
return new Promise((resolve, reject) => {
11561214
const TIMEOUT = 2000
@@ -1171,5 +1229,3 @@ function watchFileCreated (filename) {
11711229
}, INTERVAL)
11721230
})
11731231
}
1174-
1175-
function noop () {}

test/error-objects.test.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ process.env.TZ = 'UTC'
55
const Writable = require('stream').Writable
66
const test = require('tap').test
77
const pino = require('pino')
8+
const semver = require('semver')
89
const serializers = pino.stdSerializers
9-
const _prettyFactory = require('../').prettyFactory
10+
const pinoPretty = require('../')
11+
const _prettyFactory = pinoPretty.prettyFactory
1012

1113
function prettyFactory (opts) {
1214
if (!opts) {
@@ -452,3 +454,46 @@ test('error like objects tests', (t) => {
452454

453455
t.end()
454456
})
457+
458+
if (semver.gte(pino.version, '8.21.0')) {
459+
test('using pino config', (t) => {
460+
t.beforeEach(() => {
461+
Date.originalNow = Date.now
462+
Date.now = () => epoch
463+
})
464+
t.afterEach(() => {
465+
Date.now = Date.originalNow
466+
delete Date.originalNow
467+
})
468+
469+
t.test('prettifies Error in custom errorKey', (t) => {
470+
t.plan(8)
471+
const destination = new Writable({
472+
write (chunk, enc, cb) {
473+
const formatted = chunk.toString()
474+
const lines = formatted.split('\n')
475+
t.equal(lines.length, expected.length + 7)
476+
t.equal(lines[0], `[${formattedEpoch}] INFO (${pid}): hello world`)
477+
t.match(lines[1], /\s{4}customErrorKey: {/)
478+
t.match(lines[2], /\s{6}"type": "Error",/)
479+
t.match(lines[3], /\s{6}"message": "hello world",/)
480+
t.match(lines[4], /\s{6}"stack":/)
481+
t.match(lines[5], /\s{6}Error: hello world/)
482+
// Node 12 labels the test `<anonymous>`
483+
t.match(lines[6], /\s{10}(at Test.t.test|at Test.<anonymous>)/)
484+
cb()
485+
}
486+
})
487+
const pretty = pinoPretty({
488+
destination,
489+
colorize: false
490+
})
491+
const log = pino({ errorKey: 'customErrorKey' }, pretty)
492+
const err = Error('hello world')
493+
const expected = err.stack.split('\n')
494+
log.info({ customErrorKey: err })
495+
})
496+
497+
t.end()
498+
})
499+
}

0 commit comments

Comments
 (0)