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,257 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('node:test')
|
|
4
|
+
const assert = require('node:assert')
|
|
5
|
+
const stdSerializers = require('pino-std-serializers')
|
|
6
|
+
|
|
7
|
+
const { sink, once } = require('./helper')
|
|
8
|
+
const pino = require('../')
|
|
9
|
+
|
|
10
|
+
const parentSerializers = {
|
|
11
|
+
test: () => 'parent'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const childSerializers = {
|
|
15
|
+
test: () => 'child'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test('default err namespace error serializer', async () => {
|
|
19
|
+
const stream = sink()
|
|
20
|
+
const parent = pino(stream)
|
|
21
|
+
|
|
22
|
+
parent.info({ err: ReferenceError('test') })
|
|
23
|
+
const o = await once(stream, 'data')
|
|
24
|
+
assert.equal(typeof o.err, 'object')
|
|
25
|
+
assert.equal(o.err.type, 'ReferenceError')
|
|
26
|
+
assert.equal(o.err.message, 'test')
|
|
27
|
+
assert.equal(typeof o.err.stack, 'string')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('custom serializer overrides default err namespace error serializer', async () => {
|
|
31
|
+
const stream = sink()
|
|
32
|
+
const parent = pino({
|
|
33
|
+
serializers: {
|
|
34
|
+
err: (e) => ({
|
|
35
|
+
t: e.constructor.name,
|
|
36
|
+
m: e.message,
|
|
37
|
+
s: e.stack
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}, stream)
|
|
41
|
+
|
|
42
|
+
parent.info({ err: ReferenceError('test') })
|
|
43
|
+
const o = await once(stream, 'data')
|
|
44
|
+
assert.equal(typeof o.err, 'object')
|
|
45
|
+
assert.equal(o.err.t, 'ReferenceError')
|
|
46
|
+
assert.equal(o.err.m, 'test')
|
|
47
|
+
assert.equal(typeof o.err.s, 'string')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('custom serializer overrides default err namespace error serializer when nestedKey is on', async () => {
|
|
51
|
+
const stream = sink()
|
|
52
|
+
const parent = pino({
|
|
53
|
+
nestedKey: 'obj',
|
|
54
|
+
serializers: {
|
|
55
|
+
err: (e) => {
|
|
56
|
+
return {
|
|
57
|
+
t: e.constructor.name,
|
|
58
|
+
m: e.message,
|
|
59
|
+
s: e.stack
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, stream)
|
|
64
|
+
|
|
65
|
+
parent.info({ err: ReferenceError('test') })
|
|
66
|
+
const o = await once(stream, 'data')
|
|
67
|
+
assert.equal(typeof o.obj.err, 'object')
|
|
68
|
+
assert.equal(o.obj.err.t, 'ReferenceError')
|
|
69
|
+
assert.equal(o.obj.err.m, 'test')
|
|
70
|
+
assert.equal(typeof o.obj.err.s, 'string')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('null overrides default err namespace error serializer', async () => {
|
|
74
|
+
const stream = sink()
|
|
75
|
+
const parent = pino({ serializers: { err: null } }, stream)
|
|
76
|
+
|
|
77
|
+
parent.info({ err: ReferenceError('test') })
|
|
78
|
+
const o = await once(stream, 'data')
|
|
79
|
+
assert.equal(typeof o.err, 'object')
|
|
80
|
+
assert.equal(typeof o.err.type, 'undefined')
|
|
81
|
+
assert.equal(typeof o.err.message, 'undefined')
|
|
82
|
+
assert.equal(typeof o.err.stack, 'undefined')
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('undefined overrides default err namespace error serializer', async () => {
|
|
86
|
+
const stream = sink()
|
|
87
|
+
const parent = pino({ serializers: { err: undefined } }, stream)
|
|
88
|
+
|
|
89
|
+
parent.info({ err: ReferenceError('test') })
|
|
90
|
+
const o = await once(stream, 'data')
|
|
91
|
+
assert.equal(typeof o.err, 'object')
|
|
92
|
+
assert.equal(typeof o.err.type, 'undefined')
|
|
93
|
+
assert.equal(typeof o.err.message, 'undefined')
|
|
94
|
+
assert.equal(typeof o.err.stack, 'undefined')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('serializers override values', async () => {
|
|
98
|
+
const stream = sink()
|
|
99
|
+
const parent = pino({ serializers: parentSerializers }, stream)
|
|
100
|
+
parent.child({}, { serializers: childSerializers })
|
|
101
|
+
|
|
102
|
+
parent.fatal({ test: 'test' })
|
|
103
|
+
const o = await once(stream, 'data')
|
|
104
|
+
assert.equal(o.test, 'parent')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('child does not overwrite parent serializers', async () => {
|
|
108
|
+
const stream = sink()
|
|
109
|
+
const parent = pino({ serializers: parentSerializers }, stream)
|
|
110
|
+
const child = parent.child({}, { serializers: childSerializers })
|
|
111
|
+
|
|
112
|
+
parent.fatal({ test: 'test' })
|
|
113
|
+
|
|
114
|
+
const o = once(stream, 'data')
|
|
115
|
+
assert.equal((await o).test, 'parent')
|
|
116
|
+
const o2 = once(stream, 'data')
|
|
117
|
+
child.fatal({ test: 'test' })
|
|
118
|
+
assert.equal((await o2).test, 'child')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('Symbol.for(\'pino.serializers\')', async () => {
|
|
122
|
+
const stream = sink()
|
|
123
|
+
const expected = Object.assign({
|
|
124
|
+
err: stdSerializers.err
|
|
125
|
+
}, parentSerializers)
|
|
126
|
+
const parent = pino({ serializers: parentSerializers }, stream)
|
|
127
|
+
const child = parent.child({ a: 'property' })
|
|
128
|
+
|
|
129
|
+
assert.deepEqual(parent[Symbol.for('pino.serializers')], expected)
|
|
130
|
+
assert.deepEqual(child[Symbol.for('pino.serializers')], expected)
|
|
131
|
+
assert.equal(parent[Symbol.for('pino.serializers')], child[Symbol.for('pino.serializers')])
|
|
132
|
+
|
|
133
|
+
const child2 = parent.child({}, {
|
|
134
|
+
serializers: {
|
|
135
|
+
a
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
function a () {
|
|
140
|
+
return 'hello'
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// eslint-disable-next-line eqeqeq
|
|
144
|
+
assert.equal(child2[Symbol.for('pino.serializers')] != parentSerializers, true)
|
|
145
|
+
assert.equal(child2[Symbol.for('pino.serializers')].a, a)
|
|
146
|
+
assert.equal(child2[Symbol.for('pino.serializers')].test, parentSerializers.test)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('children inherit parent serializers', async () => {
|
|
150
|
+
const stream = sink()
|
|
151
|
+
const parent = pino({ serializers: parentSerializers }, stream)
|
|
152
|
+
|
|
153
|
+
const child = parent.child({ a: 'property' })
|
|
154
|
+
child.fatal({ test: 'test' })
|
|
155
|
+
const o = await once(stream, 'data')
|
|
156
|
+
assert.equal(o.test, 'parent')
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
test('children inherit parent Symbol serializers', async () => {
|
|
160
|
+
const stream = sink()
|
|
161
|
+
const symbolSerializers = {
|
|
162
|
+
[Symbol.for('b')]: b
|
|
163
|
+
}
|
|
164
|
+
const expected = Object.assign({
|
|
165
|
+
err: stdSerializers.err
|
|
166
|
+
}, symbolSerializers)
|
|
167
|
+
const parent = pino({ serializers: symbolSerializers }, stream)
|
|
168
|
+
|
|
169
|
+
assert.deepEqual(parent[Symbol.for('pino.serializers')], expected)
|
|
170
|
+
|
|
171
|
+
const child = parent.child({}, {
|
|
172
|
+
serializers: {
|
|
173
|
+
[Symbol.for('a')]: a,
|
|
174
|
+
a
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
function a () {
|
|
179
|
+
return 'hello'
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function b () {
|
|
183
|
+
return 'world'
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
assert.deepEqual(child[Symbol.for('pino.serializers')].a, a)
|
|
187
|
+
assert.deepEqual(child[Symbol.for('pino.serializers')][Symbol.for('b')], b)
|
|
188
|
+
assert.deepEqual(child[Symbol.for('pino.serializers')][Symbol.for('a')], a)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
test('children serializers get called', async () => {
|
|
192
|
+
const stream = sink()
|
|
193
|
+
const parent = pino({
|
|
194
|
+
test: 'this'
|
|
195
|
+
}, stream)
|
|
196
|
+
|
|
197
|
+
const child = parent.child({ a: 'property' }, { serializers: childSerializers })
|
|
198
|
+
|
|
199
|
+
child.fatal({ test: 'test' })
|
|
200
|
+
const o = await once(stream, 'data')
|
|
201
|
+
assert.equal(o.test, 'child')
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test('children serializers get called when inherited from parent', async () => {
|
|
205
|
+
const stream = sink()
|
|
206
|
+
const parent = pino({
|
|
207
|
+
test: 'this',
|
|
208
|
+
serializers: parentSerializers
|
|
209
|
+
}, stream)
|
|
210
|
+
|
|
211
|
+
const child = parent.child({}, { serializers: { test: function () { return 'pass' } } })
|
|
212
|
+
|
|
213
|
+
child.fatal({ test: 'fail' })
|
|
214
|
+
const o = await once(stream, 'data')
|
|
215
|
+
assert.equal(o.test, 'pass')
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
test('non-overridden serializers are available in the children', async () => {
|
|
219
|
+
const stream = sink()
|
|
220
|
+
const pSerializers = {
|
|
221
|
+
onlyParent: function () { return 'parent' },
|
|
222
|
+
shared: function () { return 'parent' }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const cSerializers = {
|
|
226
|
+
shared: function () { return 'child' },
|
|
227
|
+
onlyChild: function () { return 'child' }
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const parent = pino({ serializers: pSerializers }, stream)
|
|
231
|
+
|
|
232
|
+
const child = parent.child({}, { serializers: cSerializers })
|
|
233
|
+
|
|
234
|
+
const o = once(stream, 'data')
|
|
235
|
+
child.fatal({ shared: 'test' })
|
|
236
|
+
assert.equal((await o).shared, 'child')
|
|
237
|
+
const o2 = once(stream, 'data')
|
|
238
|
+
child.fatal({ onlyParent: 'test' })
|
|
239
|
+
assert.equal((await o2).onlyParent, 'parent')
|
|
240
|
+
const o3 = once(stream, 'data')
|
|
241
|
+
child.fatal({ onlyChild: 'test' })
|
|
242
|
+
assert.equal((await o3).onlyChild, 'child')
|
|
243
|
+
const o4 = once(stream, 'data')
|
|
244
|
+
parent.fatal({ onlyChild: 'test' })
|
|
245
|
+
assert.equal((await o4).onlyChild, 'test')
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('custom serializer for messageKey', async () => {
|
|
249
|
+
const stream = sink()
|
|
250
|
+
const instance = pino({ serializers: { msg: () => '422' } }, stream)
|
|
251
|
+
|
|
252
|
+
const o = { num: NaN }
|
|
253
|
+
instance.info(o, 42)
|
|
254
|
+
|
|
255
|
+
const { msg } = await once(stream, 'data')
|
|
256
|
+
assert.equal(msg, '422')
|
|
257
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('node:test')
|
|
4
|
+
const assert = require('node:assert')
|
|
5
|
+
const { join } = require('node:path')
|
|
6
|
+
const { fork } = require('node:child_process')
|
|
7
|
+
const writer = require('flush-write-stream')
|
|
8
|
+
|
|
9
|
+
const { once } = require('./helper')
|
|
10
|
+
const pino = require('..')
|
|
11
|
+
|
|
12
|
+
test('do not use SonicBoom is someone tampered with process.stdout.write', async () => {
|
|
13
|
+
let actual = ''
|
|
14
|
+
const child = fork(join(__dirname, 'fixtures', 'stdout-hack-protection.js'), { silent: true })
|
|
15
|
+
|
|
16
|
+
child.stdout.pipe(writer((s, enc, cb) => {
|
|
17
|
+
actual += s
|
|
18
|
+
cb()
|
|
19
|
+
}))
|
|
20
|
+
await once(child, 'close')
|
|
21
|
+
assert.equal(actual.match(/^hack/) != null, true)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('do not use SonicBoom is someone has passed process.stdout to pino', async () => {
|
|
25
|
+
const logger = pino(process.stdout)
|
|
26
|
+
assert.equal(logger[pino.symbols.streamSym], process.stdout)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('do not crash if process.stdout has no fd', async (t) => {
|
|
30
|
+
const fd = process.stdout.fd
|
|
31
|
+
delete process.stdout.fd
|
|
32
|
+
t.after(function () { process.stdout.fd = fd })
|
|
33
|
+
pino()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('use fd=1 if process.stdout has no fd in pino.destination() (worker case)', async (t) => {
|
|
37
|
+
const fd = process.stdout.fd
|
|
38
|
+
delete process.stdout.fd
|
|
39
|
+
t.after(function () { process.stdout.fd = fd })
|
|
40
|
+
pino.destination()
|
|
41
|
+
})
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('node:test')
|
|
4
|
+
const assert = require('node:assert')
|
|
5
|
+
const os = require('node:os')
|
|
6
|
+
const { promises: { readFile }, createWriteStream } = require('node:fs')
|
|
7
|
+
const { join } = require('node:path')
|
|
8
|
+
const { fork } = require('node:child_process')
|
|
9
|
+
const writer = require('flush-write-stream')
|
|
10
|
+
const {
|
|
11
|
+
once,
|
|
12
|
+
getPathToNull,
|
|
13
|
+
file,
|
|
14
|
+
watchFileCreated
|
|
15
|
+
} = require('./helper')
|
|
16
|
+
const { promisify } = require('node:util')
|
|
17
|
+
const tspl = require('@matteo.collina/tspl')
|
|
18
|
+
|
|
19
|
+
const sleep = promisify(setTimeout)
|
|
20
|
+
|
|
21
|
+
test('asynchronous logging', async (t) => {
|
|
22
|
+
const now = Date.now
|
|
23
|
+
const hostname = os.hostname
|
|
24
|
+
const proc = process
|
|
25
|
+
global.process = {
|
|
26
|
+
__proto__: process,
|
|
27
|
+
pid: 123456
|
|
28
|
+
}
|
|
29
|
+
Date.now = () => 1459875739796
|
|
30
|
+
os.hostname = () => 'abcdefghijklmnopqr'
|
|
31
|
+
delete require.cache[require.resolve('../')]
|
|
32
|
+
const pino = require('../')
|
|
33
|
+
let expected = ''
|
|
34
|
+
let actual = ''
|
|
35
|
+
const normal = pino(writer((s, enc, cb) => {
|
|
36
|
+
expected += s
|
|
37
|
+
cb()
|
|
38
|
+
}))
|
|
39
|
+
|
|
40
|
+
const dest = createWriteStream(getPathToNull())
|
|
41
|
+
dest.write = (s) => {
|
|
42
|
+
actual += s
|
|
43
|
+
}
|
|
44
|
+
const asyncLogger = pino(dest)
|
|
45
|
+
|
|
46
|
+
let i = 44
|
|
47
|
+
while (i--) {
|
|
48
|
+
normal.info('h')
|
|
49
|
+
asyncLogger.info('h')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const expected2 = expected.split('\n')[0]
|
|
53
|
+
let actual2 = ''
|
|
54
|
+
|
|
55
|
+
const child = fork(join(__dirname, '/fixtures/syncfalse.js'), { silent: true })
|
|
56
|
+
child.stdout.pipe(writer((s, enc, cb) => {
|
|
57
|
+
actual2 += s
|
|
58
|
+
cb()
|
|
59
|
+
}))
|
|
60
|
+
await once(child, 'close')
|
|
61
|
+
// Wait for the last write to be flushed
|
|
62
|
+
await sleep(100)
|
|
63
|
+
assert.equal(actual, expected)
|
|
64
|
+
assert.equal(actual2.trim(), expected2)
|
|
65
|
+
|
|
66
|
+
t.after(() => {
|
|
67
|
+
os.hostname = hostname
|
|
68
|
+
Date.now = now
|
|
69
|
+
global.process = proc
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('sync false with child', async (t) => {
|
|
74
|
+
const now = Date.now
|
|
75
|
+
const hostname = os.hostname
|
|
76
|
+
const proc = process
|
|
77
|
+
global.process = {
|
|
78
|
+
__proto__: process,
|
|
79
|
+
pid: 123456
|
|
80
|
+
}
|
|
81
|
+
Date.now = function () {
|
|
82
|
+
return 1459875739796
|
|
83
|
+
}
|
|
84
|
+
os.hostname = function () {
|
|
85
|
+
return 'abcdefghijklmnopqr'
|
|
86
|
+
}
|
|
87
|
+
delete require.cache[require.resolve('../')]
|
|
88
|
+
const pino = require('../')
|
|
89
|
+
let expected = ''
|
|
90
|
+
let actual = ''
|
|
91
|
+
const normal = pino(writer((s, enc, cb) => {
|
|
92
|
+
expected += s
|
|
93
|
+
cb()
|
|
94
|
+
})).child({ hello: 'world' })
|
|
95
|
+
|
|
96
|
+
const dest = createWriteStream(getPathToNull())
|
|
97
|
+
dest.write = function (s) {
|
|
98
|
+
actual += s
|
|
99
|
+
}
|
|
100
|
+
const asyncLogger = pino(dest).child({ hello: 'world' })
|
|
101
|
+
|
|
102
|
+
let i = 500
|
|
103
|
+
while (i--) {
|
|
104
|
+
normal.info('h')
|
|
105
|
+
asyncLogger.info('h')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
asyncLogger.flush()
|
|
109
|
+
|
|
110
|
+
const expected2 = expected.split('\n')[0]
|
|
111
|
+
let actual2 = ''
|
|
112
|
+
|
|
113
|
+
const child = fork(join(__dirname, '/fixtures/syncfalse-child.js'), { silent: true })
|
|
114
|
+
child.stdout.pipe(writer((s, enc, cb) => {
|
|
115
|
+
actual2 += s
|
|
116
|
+
cb()
|
|
117
|
+
}))
|
|
118
|
+
await once(child, 'close')
|
|
119
|
+
assert.equal(actual, expected)
|
|
120
|
+
assert.equal(actual2.trim(), expected2)
|
|
121
|
+
|
|
122
|
+
t.after(() => {
|
|
123
|
+
os.hostname = hostname
|
|
124
|
+
Date.now = now
|
|
125
|
+
global.process = proc
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('flush does nothing with sync true (default)', async () => {
|
|
130
|
+
const instance = require('..')()
|
|
131
|
+
assert.equal(instance.flush(), undefined)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('should still call flush callback even when does nothing with sync true (default)', async (t) => {
|
|
135
|
+
const plan = tspl(t, { plan: 3 })
|
|
136
|
+
const instance = require('..')()
|
|
137
|
+
instance.flush((...args) => {
|
|
138
|
+
plan.ok('flush called')
|
|
139
|
+
plan.deepEqual(args, [])
|
|
140
|
+
|
|
141
|
+
// next tick to make flush not called more than once
|
|
142
|
+
process.nextTick(() => {
|
|
143
|
+
plan.ok('flush next tick called')
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
await plan
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('should call the flush callback when flushed the data for async logger', async () => {
|
|
151
|
+
const outputPath = file()
|
|
152
|
+
async function getOutputLogLines () {
|
|
153
|
+
return (await readFile(outputPath)).toString().trim().split('\n').map(JSON.parse)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const pino = require('../')
|
|
157
|
+
|
|
158
|
+
const instance = pino({}, pino.destination({
|
|
159
|
+
dest: outputPath,
|
|
160
|
+
|
|
161
|
+
// to make sure it does not flush on its own
|
|
162
|
+
minLength: 4096
|
|
163
|
+
}))
|
|
164
|
+
const flushPromise = promisify(instance.flush).bind(instance)
|
|
165
|
+
|
|
166
|
+
instance.info('hello')
|
|
167
|
+
await flushPromise()
|
|
168
|
+
await watchFileCreated(outputPath)
|
|
169
|
+
|
|
170
|
+
const [firstFlushData] = await getOutputLogLines()
|
|
171
|
+
|
|
172
|
+
assert.equal(firstFlushData.msg, 'hello')
|
|
173
|
+
|
|
174
|
+
// should not flush this as no data accumulated that's bigger than min length
|
|
175
|
+
instance.info('world')
|
|
176
|
+
|
|
177
|
+
// Making sure data is not flushed yet
|
|
178
|
+
const afterLogData = await getOutputLogLines()
|
|
179
|
+
assert.equal(afterLogData.length, 1)
|
|
180
|
+
|
|
181
|
+
await flushPromise()
|
|
182
|
+
|
|
183
|
+
// Making sure data is not flushed yet
|
|
184
|
+
const afterSecondFlush = (await getOutputLogLines())[1]
|
|
185
|
+
assert.equal(afterSecondFlush.msg, 'world')
|
|
186
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/* eslint no-prototype-builtins: 0 */
|
|
4
|
+
|
|
5
|
+
const test = require('node:test')
|
|
6
|
+
const assert = require('node:assert')
|
|
7
|
+
|
|
8
|
+
const { sink, once } = require('./helper')
|
|
9
|
+
|
|
10
|
+
test('pino.stdTimeFunctions.isoTimeNano returns RFC 3339 timestamps', async () => {
|
|
11
|
+
// Mock Date.now at module initialization time
|
|
12
|
+
const now = Date.now
|
|
13
|
+
Date.now = () => new Date('2025-08-01T15:03:45.000000000Z').getTime()
|
|
14
|
+
|
|
15
|
+
// Mock process.hrtime.bigint at module initialization time
|
|
16
|
+
const hrTimeBigint = process.hrtime.bigint
|
|
17
|
+
process.hrtime.bigint = () => 100000000000000n
|
|
18
|
+
|
|
19
|
+
const pino = require('../')
|
|
20
|
+
|
|
21
|
+
const opts = {
|
|
22
|
+
timestamp: pino.stdTimeFunctions.isoTimeNano
|
|
23
|
+
}
|
|
24
|
+
const stream = sink()
|
|
25
|
+
|
|
26
|
+
// Mock process.hrtime.bigint at invocation time, add 1 day to the timestamp
|
|
27
|
+
process.hrtime.bigint = () => 100000000000000n + 86400012345678n
|
|
28
|
+
|
|
29
|
+
const instance = pino(opts, stream)
|
|
30
|
+
instance.info('foobar')
|
|
31
|
+
const result = await once(stream, 'data')
|
|
32
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
33
|
+
assert.equal(result.time, '2025-08-02T15:03:45.012345678Z')
|
|
34
|
+
|
|
35
|
+
Date.now = now
|
|
36
|
+
process.hrtime.bigint = hrTimeBigint
|
|
37
|
+
})
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/* eslint no-prototype-builtins: 0 */
|
|
4
|
+
|
|
5
|
+
const test = require('node:test')
|
|
6
|
+
const assert = require('node:assert')
|
|
7
|
+
|
|
8
|
+
const { sink, once } = require('./helper')
|
|
9
|
+
const pino = require('../')
|
|
10
|
+
|
|
11
|
+
test('pino exposes standard time functions', async () => {
|
|
12
|
+
assert.ok(pino.stdTimeFunctions)
|
|
13
|
+
assert.ok(pino.stdTimeFunctions.epochTime)
|
|
14
|
+
assert.ok(pino.stdTimeFunctions.unixTime)
|
|
15
|
+
assert.ok(pino.stdTimeFunctions.nullTime)
|
|
16
|
+
assert.ok(pino.stdTimeFunctions.isoTime)
|
|
17
|
+
assert.ok(pino.stdTimeFunctions.isoTimeNano)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('pino accepts external time functions', async () => {
|
|
21
|
+
const opts = {
|
|
22
|
+
timestamp: () => ',"time":"none"'
|
|
23
|
+
}
|
|
24
|
+
const stream = sink()
|
|
25
|
+
const instance = pino(opts, stream)
|
|
26
|
+
instance.info('foobar')
|
|
27
|
+
const result = await once(stream, 'data')
|
|
28
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
29
|
+
assert.equal(result.time, 'none')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('pino accepts external time functions with custom label', async () => {
|
|
33
|
+
const opts = {
|
|
34
|
+
timestamp: () => ',"custom-time-label":"none"'
|
|
35
|
+
}
|
|
36
|
+
const stream = sink()
|
|
37
|
+
const instance = pino(opts, stream)
|
|
38
|
+
instance.info('foobar')
|
|
39
|
+
const result = await once(stream, 'data')
|
|
40
|
+
assert.equal(result.hasOwnProperty('custom-time-label'), true)
|
|
41
|
+
assert.equal(result['custom-time-label'], 'none')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('inserts timestamp by default', async ({ ok, equal }) => {
|
|
45
|
+
const stream = sink()
|
|
46
|
+
const instance = pino(stream)
|
|
47
|
+
instance.info('foobar')
|
|
48
|
+
const result = await once(stream, 'data')
|
|
49
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
50
|
+
assert.ok(new Date(result.time) <= new Date(), 'time is greater than timestamp')
|
|
51
|
+
assert.equal(result.msg, 'foobar')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('omits timestamp when timestamp option is false', async () => {
|
|
55
|
+
const stream = sink()
|
|
56
|
+
const instance = pino({ timestamp: false }, stream)
|
|
57
|
+
instance.info('foobar')
|
|
58
|
+
const result = await once(stream, 'data')
|
|
59
|
+
assert.equal(result.hasOwnProperty('time'), false)
|
|
60
|
+
assert.equal(result.msg, 'foobar')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('inserts timestamp when timestamp option is true', async ({ ok, equal }) => {
|
|
64
|
+
const stream = sink()
|
|
65
|
+
const instance = pino({ timestamp: true }, stream)
|
|
66
|
+
instance.info('foobar')
|
|
67
|
+
const result = await once(stream, 'data')
|
|
68
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
69
|
+
assert.ok(new Date(result.time) <= new Date(), 'time is greater than timestamp')
|
|
70
|
+
assert.equal(result.msg, 'foobar')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('child inserts timestamp by default', async ({ ok, equal }) => {
|
|
74
|
+
const stream = sink()
|
|
75
|
+
const logger = pino(stream)
|
|
76
|
+
const instance = logger.child({ component: 'child' })
|
|
77
|
+
instance.info('foobar')
|
|
78
|
+
const result = await once(stream, 'data')
|
|
79
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
80
|
+
assert.ok(new Date(result.time) <= new Date(), 'time is greater than timestamp')
|
|
81
|
+
assert.equal(result.msg, 'foobar')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('child omits timestamp with option', async () => {
|
|
85
|
+
const stream = sink()
|
|
86
|
+
const logger = pino({ timestamp: false }, stream)
|
|
87
|
+
const instance = logger.child({ component: 'child' })
|
|
88
|
+
instance.info('foobar')
|
|
89
|
+
const result = await once(stream, 'data')
|
|
90
|
+
assert.equal(result.hasOwnProperty('time'), false)
|
|
91
|
+
assert.equal(result.msg, 'foobar')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('pino.stdTimeFunctions.unixTime returns seconds based timestamps', async () => {
|
|
95
|
+
const opts = {
|
|
96
|
+
timestamp: pino.stdTimeFunctions.unixTime
|
|
97
|
+
}
|
|
98
|
+
const stream = sink()
|
|
99
|
+
const instance = pino(opts, stream)
|
|
100
|
+
const now = Date.now
|
|
101
|
+
Date.now = () => 1531069919686
|
|
102
|
+
instance.info('foobar')
|
|
103
|
+
const result = await once(stream, 'data')
|
|
104
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
105
|
+
assert.equal(result.time, 1531069920)
|
|
106
|
+
Date.now = now
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('pino.stdTimeFunctions.isoTime returns ISO 8601 timestamps', async () => {
|
|
110
|
+
const opts = {
|
|
111
|
+
timestamp: pino.stdTimeFunctions.isoTime
|
|
112
|
+
}
|
|
113
|
+
const stream = sink()
|
|
114
|
+
const instance = pino(opts, stream)
|
|
115
|
+
const ms = 1531069919686
|
|
116
|
+
const now = Date.now
|
|
117
|
+
Date.now = () => ms
|
|
118
|
+
const iso = new Date(ms).toISOString()
|
|
119
|
+
instance.info('foobar')
|
|
120
|
+
const result = await once(stream, 'data')
|
|
121
|
+
assert.equal(result.hasOwnProperty('time'), true)
|
|
122
|
+
assert.equal(result.time, iso)
|
|
123
|
+
Date.now = now
|
|
124
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('node:test')
|
|
4
|
+
const assert = require('node:assert')
|
|
5
|
+
const { join } = require('node:path')
|
|
6
|
+
const { createReadStream } = require('node:fs')
|
|
7
|
+
const { promisify } = require('node:util')
|
|
8
|
+
const stream = require('node:stream')
|
|
9
|
+
const execa = require('execa')
|
|
10
|
+
const split = require('split2')
|
|
11
|
+
|
|
12
|
+
const { file } = require('../helper')
|
|
13
|
+
|
|
14
|
+
const pipeline = promisify(stream.pipeline)
|
|
15
|
+
const { Writable } = stream
|
|
16
|
+
const sleep = promisify(setTimeout)
|
|
17
|
+
|
|
18
|
+
const skip = process.env.CI || process.env.CITGM
|
|
19
|
+
|
|
20
|
+
test('eight million lines', { skip }, async () => {
|
|
21
|
+
const destination = file()
|
|
22
|
+
await execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-many-lines.js'), destination])
|
|
23
|
+
|
|
24
|
+
if (process.platform !== 'win32') {
|
|
25
|
+
try {
|
|
26
|
+
await execa('sync') // Wait for the file to be written to disk
|
|
27
|
+
} catch {
|
|
28
|
+
// Just a fallback, this should be unreachable
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
await sleep(1_000) // It seems that sync is not enough (even in POSIX systems)
|
|
32
|
+
|
|
33
|
+
const toWrite = 8 * 1_000_000
|
|
34
|
+
let count = 0
|
|
35
|
+
await pipeline(createReadStream(destination), split(), new Writable({
|
|
36
|
+
write (chunk, enc, cb) {
|
|
37
|
+
count++
|
|
38
|
+
cb()
|
|
39
|
+
}
|
|
40
|
+
}))
|
|
41
|
+
assert.equal(count, toWrite)
|
|
42
|
+
})
|