pino-testkit 10.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nojekyll +0 -0
- package/.prettierignore +1 -0
- package/CNAME +1 -0
- package/CONTRIBUTING.md +30 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/SECURITY.md +87 -0
- package/benchmarks/basic.bench.js +95 -0
- package/benchmarks/child-child.bench.js +52 -0
- package/benchmarks/child-creation.bench.js +73 -0
- package/benchmarks/child.bench.js +62 -0
- package/benchmarks/deep-object.bench.js +88 -0
- package/benchmarks/formatters.bench.js +50 -0
- package/benchmarks/internal/custom-levels.js +67 -0
- package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
- package/benchmarks/internal/just-pino.bench.js +182 -0
- package/benchmarks/internal/parent-vs-child.bench.js +75 -0
- package/benchmarks/internal/redact.bench.js +86 -0
- package/benchmarks/long-string.bench.js +81 -0
- package/benchmarks/multi-arg.bench.js +193 -0
- package/benchmarks/multistream.js +98 -0
- package/benchmarks/object.bench.js +82 -0
- package/benchmarks/utils/generate-benchmark-doc.js +36 -0
- package/benchmarks/utils/runbench.js +138 -0
- package/benchmarks/utils/wrap-log-level.js +55 -0
- package/bin.js +6 -0
- package/browser.js +547 -0
- package/build/sync-version.js +25 -0
- package/docs/api.md +1593 -0
- package/docs/asynchronous.md +40 -0
- package/docs/benchmarks.md +55 -0
- package/docs/browser.md +278 -0
- package/docs/bundling.md +40 -0
- package/docs/child-loggers.md +95 -0
- package/docs/diagnostics.md +16 -0
- package/docs/ecosystem.md +86 -0
- package/docs/help.md +345 -0
- package/docs/lts.md +64 -0
- package/docs/pretty.md +35 -0
- package/docs/redaction.md +135 -0
- package/docs/transports.md +1376 -0
- package/docs/web.md +309 -0
- package/eslint.config.js +28 -0
- package/examples/basic.js +43 -0
- package/examples/transport.js +68 -0
- package/favicon.ico +0 -0
- package/file.js +12 -0
- package/inc-version.sh +42 -0
- package/index.html +55 -0
- package/lib/caller.js +30 -0
- package/lib/constants.js +28 -0
- package/lib/contract.js +8 -0
- package/lib/deprecations.js +8 -0
- package/lib/levels.js +241 -0
- package/lib/meta.js +3 -0
- package/lib/multistream.js +203 -0
- package/lib/proto.js +256 -0
- package/lib/redaction.js +114 -0
- package/lib/symbols.js +74 -0
- package/lib/time.js +39 -0
- package/lib/tools.js +427 -0
- package/lib/transport-stream.js +56 -0
- package/lib/transport.js +289 -0
- package/lib/worker.js +194 -0
- package/package.json +119 -0
- package/pino.d.ts +908 -0
- package/pino.js +240 -0
- package/test/basic.test.js +886 -0
- package/test/broken-pipe.test.js +59 -0
- package/test/browser-child.test.js +132 -0
- package/test/browser-disabled.test.js +87 -0
- package/test/browser-early-console-freeze.test.js +12 -0
- package/test/browser-is-level-enabled.test.js +101 -0
- package/test/browser-levels.test.js +241 -0
- package/test/browser-serializers.test.js +352 -0
- package/test/browser-timestamp.test.js +88 -0
- package/test/browser-transmit.test.js +417 -0
- package/test/browser.test.js +698 -0
- package/test/complex-objects.test.js +36 -0
- package/test/crlf.test.js +34 -0
- package/test/custom-levels.test.js +267 -0
- package/test/diagnostics.test.js +107 -0
- package/test/error-key.test.js +37 -0
- package/test/error.test.js +403 -0
- package/test/escaping.test.js +93 -0
- package/test/esm/esm.mjs +14 -0
- package/test/esm/index.test.js +21 -0
- package/test/esm/named-exports.mjs +29 -0
- package/test/exit.test.js +79 -0
- package/test/fixtures/broken-pipe/basic.js +9 -0
- package/test/fixtures/broken-pipe/destination.js +10 -0
- package/test/fixtures/broken-pipe/syncfalse.js +12 -0
- package/test/fixtures/console-transport.js +13 -0
- package/test/fixtures/crashing-transport.js +13 -0
- package/test/fixtures/default-exit.js +8 -0
- package/test/fixtures/destination-exit.js +8 -0
- package/test/fixtures/eval/index.js +13 -0
- package/test/fixtures/eval/node_modules/14-files.js +3 -0
- package/test/fixtures/eval/node_modules/2-files.js +3 -0
- package/test/fixtures/eval/node_modules/file1.js +5 -0
- package/test/fixtures/eval/node_modules/file10.js +5 -0
- package/test/fixtures/eval/node_modules/file11.js +5 -0
- package/test/fixtures/eval/node_modules/file12.js +5 -0
- package/test/fixtures/eval/node_modules/file13.js +5 -0
- package/test/fixtures/eval/node_modules/file14.js +11 -0
- package/test/fixtures/eval/node_modules/file2.js +5 -0
- package/test/fixtures/eval/node_modules/file3.js +5 -0
- package/test/fixtures/eval/node_modules/file4.js +5 -0
- package/test/fixtures/eval/node_modules/file5.js +5 -0
- package/test/fixtures/eval/node_modules/file6.js +5 -0
- package/test/fixtures/eval/node_modules/file7.js +5 -0
- package/test/fixtures/eval/node_modules/file8.js +5 -0
- package/test/fixtures/eval/node_modules/file9.js +5 -0
- package/test/fixtures/noop-transport.js +10 -0
- package/test/fixtures/pretty/null-prototype.js +8 -0
- package/test/fixtures/stdout-hack-protection.js +11 -0
- package/test/fixtures/syncfalse-child.js +6 -0
- package/test/fixtures/syncfalse-exit.js +9 -0
- package/test/fixtures/syncfalse-flush-exit.js +10 -0
- package/test/fixtures/syncfalse.js +6 -0
- package/test/fixtures/syntax-error-esm.mjs +2 -0
- package/test/fixtures/to-file-transport-with-transform.js +20 -0
- package/test/fixtures/to-file-transport.js +13 -0
- package/test/fixtures/to-file-transport.mjs +8 -0
- package/test/fixtures/transport/index.js +12 -0
- package/test/fixtures/transport/package.json +5 -0
- package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
- package/test/fixtures/transport-exit-immediately.js +11 -0
- package/test/fixtures/transport-exit-on-ready.js +12 -0
- package/test/fixtures/transport-invalid-node-options.js +26 -0
- package/test/fixtures/transport-main.js +9 -0
- package/test/fixtures/transport-many-lines.js +29 -0
- package/test/fixtures/transport-preload-main.mjs +13 -0
- package/test/fixtures/transport-preload.mjs +13 -0
- package/test/fixtures/transport-string-stdout.js +9 -0
- package/test/fixtures/transport-transform.js +21 -0
- package/test/fixtures/transport-uses-pino-config.js +33 -0
- package/test/fixtures/transport-with-on-exit.js +12 -0
- package/test/fixtures/transport-worker-data.js +19 -0
- package/test/fixtures/transport-worker-name.js +24 -0
- package/test/fixtures/transport-worker.js +15 -0
- package/test/fixtures/transport-wrong-export-type.js +3 -0
- package/test/fixtures/ts/to-file-transport-native.mts +15 -0
- package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
- package/test/fixtures/ts/to-file-transport.ts +11 -0
- package/test/fixtures/ts/transpile.cjs +36 -0
- package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
- package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
- package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
- package/test/fixtures/ts/transport-main.ts +8 -0
- package/test/fixtures/ts/transport-string-stdout.ts +8 -0
- package/test/fixtures/ts/transport-worker.ts +14 -0
- package/test/formatters.test.js +364 -0
- package/test/helper.d.ts +4 -0
- package/test/helper.js +155 -0
- package/test/hooks.test.js +114 -0
- package/test/http.test.js +214 -0
- package/test/internals/version.test.js +17 -0
- package/test/is-level-enabled.test.js +179 -0
- package/test/jest/basic.spec.js +10 -0
- package/test/levels.test.js +810 -0
- package/test/metadata.test.js +120 -0
- package/test/mixin-merge-strategy.test.js +57 -0
- package/test/mixin.test.js +241 -0
- package/test/multistream.test.js +729 -0
- package/test/redact.test.js +893 -0
- package/test/serializers.test.js +257 -0
- package/test/stdout-protection.test.js +41 -0
- package/test/syncfalse.test.js +186 -0
- package/test/timestamp-nano.test.js +37 -0
- package/test/timestamp.test.js +124 -0
- package/test/transport/big.test.js +42 -0
- package/test/transport/bundlers-support.test.js +99 -0
- package/test/transport/caller.test.js +24 -0
- package/test/transport/core.test.js +733 -0
- package/test/transport/core.transpiled.test.ts +114 -0
- package/test/transport/crash.test.js +36 -0
- package/test/transport/module-link.test.js +241 -0
- package/test/transport/native-type-stripping.test.mjs +151 -0
- package/test/transport/node-options.test.js +116 -0
- package/test/transport/pipeline.test.js +137 -0
- package/test/transport/preload.test.js +54 -0
- package/test/transport/repl.test.js +15 -0
- package/test/transport/sync-false.test.js +67 -0
- package/test/transport/sync-true.test.js +57 -0
- package/test/transport/targets.test.js +48 -0
- package/test/transport/uses-pino-config.test.js +166 -0
- package/test/transport-stream.test.js +40 -0
- package/test/types/pino-import.test-d.cts +30 -0
- package/test/types/pino-multistream.test-d.ts +28 -0
- package/test/types/pino-top-export.test-d.ts +34 -0
- package/test/types/pino-transport.test-d.ts +156 -0
- package/test/types/pino-type-only.test-d.ts +75 -0
- package/test/types/pino.test-d.ts +683 -0
- package/test/types/pino.ts +91 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const execa = require('execa')
|
|
4
|
+
const fs = require('node:fs')
|
|
5
|
+
|
|
6
|
+
const existsSync = fs.existsSync
|
|
7
|
+
const stat = fs.promises.stat
|
|
8
|
+
|
|
9
|
+
// Hardcoded parameters
|
|
10
|
+
const esVersions = ['es5', 'es6', 'es2017', 'esnext']
|
|
11
|
+
const filesToTranspile = ['to-file-transport.ts']
|
|
12
|
+
|
|
13
|
+
async function transpile () {
|
|
14
|
+
process.chdir(__dirname)
|
|
15
|
+
|
|
16
|
+
for (const sourceFileName of filesToTranspile) {
|
|
17
|
+
const sourceStat = await stat(sourceFileName)
|
|
18
|
+
|
|
19
|
+
for (const esVersion of esVersions) {
|
|
20
|
+
const intermediateFileName = sourceFileName.replace(/\.ts$/, '.js')
|
|
21
|
+
const targetFileName = sourceFileName.replace(/\.ts$/, `.${esVersion}.cjs`)
|
|
22
|
+
|
|
23
|
+
const shouldTranspile = !existsSync(targetFileName) || (await stat(targetFileName)).mtimeMs < sourceStat.mtimeMs
|
|
24
|
+
|
|
25
|
+
if (shouldTranspile) {
|
|
26
|
+
await execa('tsc', ['--target', esVersion, '--module', 'commonjs', sourceFileName])
|
|
27
|
+
await execa('mv', [intermediateFileName, targetFileName])
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
transpile().catch(err => {
|
|
34
|
+
process.exitCode = 1
|
|
35
|
+
throw err
|
|
36
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pino from '../../..'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
const transport = pino.transport({
|
|
5
|
+
target: join(__dirname, 'to-file-transport-with-transform.ts'),
|
|
6
|
+
options: {
|
|
7
|
+
destination: process.argv[2]
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
const logger = pino(transport)
|
|
11
|
+
|
|
12
|
+
logger.info('Hello')
|
|
13
|
+
logger.info('World')
|
|
14
|
+
|
|
15
|
+
process.exit(0)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Writable } from 'node:stream'
|
|
2
|
+
|
|
3
|
+
export default (): Writable => {
|
|
4
|
+
const myTransportStream = new Writable({
|
|
5
|
+
autoDestroy: true,
|
|
6
|
+
write (chunk, _enc, cb) {
|
|
7
|
+
console.log(chunk.toString())
|
|
8
|
+
cb()
|
|
9
|
+
},
|
|
10
|
+
defaultEncoding: 'utf8'
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return myTransportStream
|
|
14
|
+
}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
/* eslint no-prototype-builtins: 0 */
|
|
3
|
+
|
|
4
|
+
const test = require('node:test')
|
|
5
|
+
const assert = require('node:assert')
|
|
6
|
+
const { hostname } = require('node:os')
|
|
7
|
+
const { join } = require('node:path')
|
|
8
|
+
const { readFile } = require('node:fs').promises
|
|
9
|
+
const tspl = require('@matteo.collina/tspl')
|
|
10
|
+
|
|
11
|
+
const { sink, match, once, watchFileCreated, file } = require('./helper')
|
|
12
|
+
const pino = require('../')
|
|
13
|
+
|
|
14
|
+
test('level formatter', async () => {
|
|
15
|
+
const stream = sink()
|
|
16
|
+
const logger = pino({
|
|
17
|
+
formatters: {
|
|
18
|
+
level (label, number) {
|
|
19
|
+
return {
|
|
20
|
+
log: {
|
|
21
|
+
level: label
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}, stream)
|
|
27
|
+
|
|
28
|
+
const o = once(stream, 'data')
|
|
29
|
+
logger.info('hello world')
|
|
30
|
+
match(await o, {
|
|
31
|
+
log: {
|
|
32
|
+
level: 'info'
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('bindings formatter', async () => {
|
|
38
|
+
const stream = sink()
|
|
39
|
+
const logger = pino({
|
|
40
|
+
formatters: {
|
|
41
|
+
bindings (bindings) {
|
|
42
|
+
return {
|
|
43
|
+
process: {
|
|
44
|
+
pid: bindings.pid
|
|
45
|
+
},
|
|
46
|
+
host: {
|
|
47
|
+
name: bindings.hostname
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}, stream)
|
|
53
|
+
|
|
54
|
+
const o = once(stream, 'data')
|
|
55
|
+
logger.info('hello world')
|
|
56
|
+
match(await o, {
|
|
57
|
+
process: {
|
|
58
|
+
pid: process.pid
|
|
59
|
+
},
|
|
60
|
+
host: {
|
|
61
|
+
name: hostname()
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('no bindings formatter', async () => {
|
|
67
|
+
const stream = sink()
|
|
68
|
+
const logger = pino({
|
|
69
|
+
formatters: {
|
|
70
|
+
bindings (bindings) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}, stream)
|
|
75
|
+
|
|
76
|
+
const o = once(stream, 'data')
|
|
77
|
+
logger.info('hello world')
|
|
78
|
+
const log = await o
|
|
79
|
+
assert.equal(log.hasOwnProperty('pid'), false)
|
|
80
|
+
assert.equal(log.hasOwnProperty('hostname'), false)
|
|
81
|
+
match(log, { msg: 'hello world' })
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('log formatter', async (t) => {
|
|
85
|
+
const plan = tspl(t, { plan: 1 })
|
|
86
|
+
const stream = sink()
|
|
87
|
+
const logger = pino({
|
|
88
|
+
formatters: {
|
|
89
|
+
log (obj) {
|
|
90
|
+
plan.equal(obj.hasOwnProperty('msg'), false)
|
|
91
|
+
return { hello: 'world', ...obj }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}, stream)
|
|
95
|
+
|
|
96
|
+
const o = once(stream, 'data')
|
|
97
|
+
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
|
98
|
+
match(await o, {
|
|
99
|
+
hello: 'world',
|
|
100
|
+
foo: 'bar',
|
|
101
|
+
nested: { object: true }
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
await plan
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('Formatters combined', async () => {
|
|
108
|
+
const stream = sink()
|
|
109
|
+
const logger = pino({
|
|
110
|
+
formatters: {
|
|
111
|
+
level (label, number) {
|
|
112
|
+
return {
|
|
113
|
+
log: {
|
|
114
|
+
level: label
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
bindings (bindings) {
|
|
119
|
+
return {
|
|
120
|
+
process: {
|
|
121
|
+
pid: bindings.pid
|
|
122
|
+
},
|
|
123
|
+
host: {
|
|
124
|
+
name: bindings.hostname
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
log (obj) {
|
|
129
|
+
return { hello: 'world', ...obj }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}, stream)
|
|
133
|
+
|
|
134
|
+
const o = once(stream, 'data')
|
|
135
|
+
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
|
136
|
+
match(await o, {
|
|
137
|
+
log: {
|
|
138
|
+
level: 'info'
|
|
139
|
+
},
|
|
140
|
+
process: {
|
|
141
|
+
pid: process.pid
|
|
142
|
+
},
|
|
143
|
+
host: {
|
|
144
|
+
name: hostname()
|
|
145
|
+
},
|
|
146
|
+
hello: 'world',
|
|
147
|
+
foo: 'bar',
|
|
148
|
+
nested: { object: true }
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('Formatters in child logger', async () => {
|
|
153
|
+
const stream = sink()
|
|
154
|
+
const logger = pino({
|
|
155
|
+
formatters: {
|
|
156
|
+
level (label, number) {
|
|
157
|
+
return {
|
|
158
|
+
log: {
|
|
159
|
+
level: label
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
bindings (bindings) {
|
|
164
|
+
return {
|
|
165
|
+
process: {
|
|
166
|
+
pid: bindings.pid
|
|
167
|
+
},
|
|
168
|
+
host: {
|
|
169
|
+
name: bindings.hostname
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
log (obj) {
|
|
174
|
+
return { hello: 'world', ...obj }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}, stream)
|
|
178
|
+
|
|
179
|
+
const child = logger.child({
|
|
180
|
+
foo: 'bar',
|
|
181
|
+
nested: { object: true }
|
|
182
|
+
}, {
|
|
183
|
+
formatters: {
|
|
184
|
+
bindings (bindings) {
|
|
185
|
+
return { ...bindings, faz: 'baz' }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const o = once(stream, 'data')
|
|
191
|
+
child.info('hello world')
|
|
192
|
+
match(await o, {
|
|
193
|
+
log: {
|
|
194
|
+
level: 'info'
|
|
195
|
+
},
|
|
196
|
+
process: {
|
|
197
|
+
pid: process.pid
|
|
198
|
+
},
|
|
199
|
+
host: {
|
|
200
|
+
name: hostname()
|
|
201
|
+
},
|
|
202
|
+
hello: 'world',
|
|
203
|
+
foo: 'bar',
|
|
204
|
+
nested: { object: true },
|
|
205
|
+
faz: 'baz'
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('Formatters without bindings in child logger', async () => {
|
|
210
|
+
const stream = sink()
|
|
211
|
+
const logger = pino({
|
|
212
|
+
formatters: {
|
|
213
|
+
level (label, number) {
|
|
214
|
+
return {
|
|
215
|
+
log: {
|
|
216
|
+
level: label
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
bindings (bindings) {
|
|
221
|
+
return {
|
|
222
|
+
process: {
|
|
223
|
+
pid: bindings.pid
|
|
224
|
+
},
|
|
225
|
+
host: {
|
|
226
|
+
name: bindings.hostname
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
log (obj) {
|
|
231
|
+
return { hello: 'world', ...obj }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}, stream)
|
|
235
|
+
|
|
236
|
+
const child = logger.child({
|
|
237
|
+
foo: 'bar',
|
|
238
|
+
nested: { object: true }
|
|
239
|
+
}, {
|
|
240
|
+
formatters: {
|
|
241
|
+
log (obj) {
|
|
242
|
+
return { other: 'stuff', ...obj }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
const o = once(stream, 'data')
|
|
248
|
+
child.info('hello world')
|
|
249
|
+
match(await o, {
|
|
250
|
+
log: {
|
|
251
|
+
level: 'info'
|
|
252
|
+
},
|
|
253
|
+
process: {
|
|
254
|
+
pid: process.pid
|
|
255
|
+
},
|
|
256
|
+
host: {
|
|
257
|
+
name: hostname()
|
|
258
|
+
},
|
|
259
|
+
foo: 'bar',
|
|
260
|
+
other: 'stuff',
|
|
261
|
+
nested: { object: true }
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
test('elastic common schema format', async () => {
|
|
266
|
+
const stream = sink()
|
|
267
|
+
const ecs = {
|
|
268
|
+
formatters: {
|
|
269
|
+
level (label, number) {
|
|
270
|
+
return {
|
|
271
|
+
log: {
|
|
272
|
+
level: label,
|
|
273
|
+
logger: 'pino'
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
bindings (bindings) {
|
|
278
|
+
return {
|
|
279
|
+
process: {
|
|
280
|
+
pid: bindings.pid
|
|
281
|
+
},
|
|
282
|
+
host: {
|
|
283
|
+
name: bindings.hostname
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
log (obj) {
|
|
288
|
+
return { ecs: { version: '1.4.0' }, ...obj }
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
messageKey: 'message',
|
|
292
|
+
timestamp: () => `,"@timestamp":"${new Date(Date.now()).toISOString()}"`
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const logger = pino({ ...ecs }, stream)
|
|
296
|
+
|
|
297
|
+
const o = once(stream, 'data')
|
|
298
|
+
logger.info({ foo: 'bar' }, 'hello world')
|
|
299
|
+
const log = await o
|
|
300
|
+
assert.equal(typeof log['@timestamp'], 'string')
|
|
301
|
+
match(log, {
|
|
302
|
+
log: { level: 'info', logger: 'pino' },
|
|
303
|
+
process: { pid: process.pid },
|
|
304
|
+
host: { name: hostname() },
|
|
305
|
+
ecs: { version: '1.4.0' },
|
|
306
|
+
foo: 'bar',
|
|
307
|
+
message: 'hello world'
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
test('formatter with transport', async (t) => {
|
|
312
|
+
const plan = tspl(t, { plan: 1 })
|
|
313
|
+
const destination = file()
|
|
314
|
+
const logger = pino({
|
|
315
|
+
formatters: {
|
|
316
|
+
log (obj) {
|
|
317
|
+
plan.equal(obj.hasOwnProperty('msg'), false)
|
|
318
|
+
return { hello: 'world', ...obj }
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
transport: {
|
|
322
|
+
targets: [
|
|
323
|
+
{
|
|
324
|
+
target: join(__dirname, 'fixtures', 'to-file-transport.js'),
|
|
325
|
+
options: { destination }
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
|
|
332
|
+
await watchFileCreated(destination)
|
|
333
|
+
const result = JSON.parse(await readFile(destination))
|
|
334
|
+
delete result.time
|
|
335
|
+
match(result, {
|
|
336
|
+
hello: 'world',
|
|
337
|
+
foo: 'bar',
|
|
338
|
+
nested: { object: true }
|
|
339
|
+
})
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
test('throws when custom level formatter is used with transport.targets', async () => {
|
|
343
|
+
assert.throws(
|
|
344
|
+
() => {
|
|
345
|
+
pino({
|
|
346
|
+
formatters: {
|
|
347
|
+
level (label) {
|
|
348
|
+
return label
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
transport: {
|
|
352
|
+
targets: [
|
|
353
|
+
{
|
|
354
|
+
target: 'pino/file',
|
|
355
|
+
options: { destination: 'foo.log' }
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
)
|
|
361
|
+
},
|
|
362
|
+
Error('option.transport.targets do not allow custom level formatters')
|
|
363
|
+
)
|
|
364
|
+
})
|
package/test/helper.d.ts
ADDED
package/test/helper.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto')
|
|
4
|
+
const { join } = require('node:path')
|
|
5
|
+
const os = require('node:os')
|
|
6
|
+
const { existsSync, readFileSync, statSync, unlinkSync } = require('node:fs')
|
|
7
|
+
const writer = require('flush-write-stream')
|
|
8
|
+
const split = require('split2')
|
|
9
|
+
|
|
10
|
+
const pid = process.pid
|
|
11
|
+
const hostname = os.hostname()
|
|
12
|
+
const { tmpdir } = os
|
|
13
|
+
|
|
14
|
+
const isWin = process.platform === 'win32'
|
|
15
|
+
const isYarnPnp = process.versions.pnp !== undefined
|
|
16
|
+
|
|
17
|
+
function getPathToNull () {
|
|
18
|
+
return isWin ? '\\\\.\\NUL' : '/dev/null'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function once (emitter, name) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
if (name !== 'error') emitter.once('error', reject)
|
|
24
|
+
emitter.once(name, (...args) => {
|
|
25
|
+
emitter.removeListener('error', reject)
|
|
26
|
+
resolve(...args)
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sink (func) {
|
|
32
|
+
const result = split((data) => {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(data)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.log(err)
|
|
37
|
+
console.log(data)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
if (func) result.pipe(writer.obj(func))
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function check (is, chunk, level, msg) {
|
|
45
|
+
is(new Date(chunk.time) <= new Date(), true, 'time is greater than Date.now()')
|
|
46
|
+
delete chunk.time
|
|
47
|
+
is(chunk.pid, pid)
|
|
48
|
+
is(chunk.hostname, hostname)
|
|
49
|
+
is(chunk.level, level)
|
|
50
|
+
is(chunk.msg, msg)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sleep (ms) {
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
setTimeout(resolve, ms)
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function watchFileCreated (filename) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const TIMEOUT = process.env.PINO_TEST_WAIT_WATCHFILE_TIMEOUT || 10000
|
|
62
|
+
const INTERVAL = 100
|
|
63
|
+
const threshold = TIMEOUT / INTERVAL
|
|
64
|
+
let counter = 0
|
|
65
|
+
const interval = setInterval(() => {
|
|
66
|
+
const exists = existsSync(filename)
|
|
67
|
+
// On some CI runs file is created but not filled
|
|
68
|
+
if (exists && statSync(filename).size !== 0) {
|
|
69
|
+
clearInterval(interval)
|
|
70
|
+
resolve()
|
|
71
|
+
} else if (counter <= threshold) {
|
|
72
|
+
counter++
|
|
73
|
+
} else {
|
|
74
|
+
clearInterval(interval)
|
|
75
|
+
reject(new Error(
|
|
76
|
+
`${filename} hasn't been created within ${TIMEOUT} ms. ` +
|
|
77
|
+
(exists ? 'File exist, but still empty.' : 'File not yet created.')
|
|
78
|
+
))
|
|
79
|
+
}
|
|
80
|
+
}, INTERVAL)
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function watchForWrite (filename, testString) {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
const TIMEOUT = process.env.PINO_TEST_WAIT_WRITE_TIMEOUT || 10000
|
|
87
|
+
const INTERVAL = 100
|
|
88
|
+
const threshold = TIMEOUT / INTERVAL
|
|
89
|
+
let counter = 0
|
|
90
|
+
const interval = setInterval(() => {
|
|
91
|
+
if (readFileSync(filename).includes(testString)) {
|
|
92
|
+
clearInterval(interval)
|
|
93
|
+
resolve()
|
|
94
|
+
} else if (counter <= threshold) {
|
|
95
|
+
counter++
|
|
96
|
+
} else {
|
|
97
|
+
clearInterval(interval)
|
|
98
|
+
reject(new Error(`'${testString}' hasn't been written to ${filename} within ${TIMEOUT} ms.`))
|
|
99
|
+
}
|
|
100
|
+
}, INTERVAL)
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let files = []
|
|
105
|
+
|
|
106
|
+
function file () {
|
|
107
|
+
const hash = crypto.randomBytes(12).toString('hex')
|
|
108
|
+
const file = join(tmpdir(), `pino-${pid}-${hash}`)
|
|
109
|
+
files.push(file)
|
|
110
|
+
return file
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
process.on('beforeExit', () => {
|
|
114
|
+
if (files.length === 0) return
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
try {
|
|
117
|
+
unlinkSync(file)
|
|
118
|
+
} catch (e) {
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
files = []
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* match is a bare-bones object shape matcher. We should be able to replace
|
|
126
|
+
* this with `assert.partialDeepStrictEqual` when v22 is our minimum.
|
|
127
|
+
*
|
|
128
|
+
* @param {object} found
|
|
129
|
+
* @param {object} expected
|
|
130
|
+
*/
|
|
131
|
+
function match (found, expected) {
|
|
132
|
+
for (const [key, value] of Object.entries(expected)) {
|
|
133
|
+
if (Object.prototype.toString.call(value) === '[object Object]') {
|
|
134
|
+
match(found[key], value)
|
|
135
|
+
continue
|
|
136
|
+
}
|
|
137
|
+
if (value !== found[key]) {
|
|
138
|
+
throw Error(`expected "${value}" but found "${found[key]}"`)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
check,
|
|
145
|
+
file,
|
|
146
|
+
getPathToNull,
|
|
147
|
+
isWin,
|
|
148
|
+
isYarnPnp,
|
|
149
|
+
match,
|
|
150
|
+
once,
|
|
151
|
+
sink,
|
|
152
|
+
sleep,
|
|
153
|
+
watchFileCreated,
|
|
154
|
+
watchForWrite
|
|
155
|
+
}
|