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.
Files changed (196) hide show
  1. package/.nojekyll +0 -0
  2. package/.prettierignore +1 -0
  3. package/CNAME +1 -0
  4. package/CONTRIBUTING.md +30 -0
  5. package/LICENSE +21 -0
  6. package/README.md +175 -0
  7. package/SECURITY.md +87 -0
  8. package/benchmarks/basic.bench.js +95 -0
  9. package/benchmarks/child-child.bench.js +52 -0
  10. package/benchmarks/child-creation.bench.js +73 -0
  11. package/benchmarks/child.bench.js +62 -0
  12. package/benchmarks/deep-object.bench.js +88 -0
  13. package/benchmarks/formatters.bench.js +50 -0
  14. package/benchmarks/internal/custom-levels.js +67 -0
  15. package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
  16. package/benchmarks/internal/just-pino.bench.js +182 -0
  17. package/benchmarks/internal/parent-vs-child.bench.js +75 -0
  18. package/benchmarks/internal/redact.bench.js +86 -0
  19. package/benchmarks/long-string.bench.js +81 -0
  20. package/benchmarks/multi-arg.bench.js +193 -0
  21. package/benchmarks/multistream.js +98 -0
  22. package/benchmarks/object.bench.js +82 -0
  23. package/benchmarks/utils/generate-benchmark-doc.js +36 -0
  24. package/benchmarks/utils/runbench.js +138 -0
  25. package/benchmarks/utils/wrap-log-level.js +55 -0
  26. package/bin.js +6 -0
  27. package/browser.js +547 -0
  28. package/build/sync-version.js +25 -0
  29. package/docs/api.md +1593 -0
  30. package/docs/asynchronous.md +40 -0
  31. package/docs/benchmarks.md +55 -0
  32. package/docs/browser.md +278 -0
  33. package/docs/bundling.md +40 -0
  34. package/docs/child-loggers.md +95 -0
  35. package/docs/diagnostics.md +16 -0
  36. package/docs/ecosystem.md +86 -0
  37. package/docs/help.md +345 -0
  38. package/docs/lts.md +64 -0
  39. package/docs/pretty.md +35 -0
  40. package/docs/redaction.md +135 -0
  41. package/docs/transports.md +1376 -0
  42. package/docs/web.md +309 -0
  43. package/eslint.config.js +28 -0
  44. package/examples/basic.js +43 -0
  45. package/examples/transport.js +68 -0
  46. package/favicon.ico +0 -0
  47. package/file.js +12 -0
  48. package/inc-version.sh +42 -0
  49. package/index.html +55 -0
  50. package/lib/caller.js +30 -0
  51. package/lib/constants.js +28 -0
  52. package/lib/contract.js +8 -0
  53. package/lib/deprecations.js +8 -0
  54. package/lib/levels.js +241 -0
  55. package/lib/meta.js +3 -0
  56. package/lib/multistream.js +203 -0
  57. package/lib/proto.js +256 -0
  58. package/lib/redaction.js +114 -0
  59. package/lib/symbols.js +74 -0
  60. package/lib/time.js +39 -0
  61. package/lib/tools.js +427 -0
  62. package/lib/transport-stream.js +56 -0
  63. package/lib/transport.js +289 -0
  64. package/lib/worker.js +194 -0
  65. package/package.json +119 -0
  66. package/pino.d.ts +908 -0
  67. package/pino.js +240 -0
  68. package/test/basic.test.js +886 -0
  69. package/test/broken-pipe.test.js +59 -0
  70. package/test/browser-child.test.js +132 -0
  71. package/test/browser-disabled.test.js +87 -0
  72. package/test/browser-early-console-freeze.test.js +12 -0
  73. package/test/browser-is-level-enabled.test.js +101 -0
  74. package/test/browser-levels.test.js +241 -0
  75. package/test/browser-serializers.test.js +352 -0
  76. package/test/browser-timestamp.test.js +88 -0
  77. package/test/browser-transmit.test.js +417 -0
  78. package/test/browser.test.js +698 -0
  79. package/test/complex-objects.test.js +36 -0
  80. package/test/crlf.test.js +34 -0
  81. package/test/custom-levels.test.js +267 -0
  82. package/test/diagnostics.test.js +107 -0
  83. package/test/error-key.test.js +37 -0
  84. package/test/error.test.js +403 -0
  85. package/test/escaping.test.js +93 -0
  86. package/test/esm/esm.mjs +14 -0
  87. package/test/esm/index.test.js +21 -0
  88. package/test/esm/named-exports.mjs +29 -0
  89. package/test/exit.test.js +79 -0
  90. package/test/fixtures/broken-pipe/basic.js +9 -0
  91. package/test/fixtures/broken-pipe/destination.js +10 -0
  92. package/test/fixtures/broken-pipe/syncfalse.js +12 -0
  93. package/test/fixtures/console-transport.js +13 -0
  94. package/test/fixtures/crashing-transport.js +13 -0
  95. package/test/fixtures/default-exit.js +8 -0
  96. package/test/fixtures/destination-exit.js +8 -0
  97. package/test/fixtures/eval/index.js +13 -0
  98. package/test/fixtures/eval/node_modules/14-files.js +3 -0
  99. package/test/fixtures/eval/node_modules/2-files.js +3 -0
  100. package/test/fixtures/eval/node_modules/file1.js +5 -0
  101. package/test/fixtures/eval/node_modules/file10.js +5 -0
  102. package/test/fixtures/eval/node_modules/file11.js +5 -0
  103. package/test/fixtures/eval/node_modules/file12.js +5 -0
  104. package/test/fixtures/eval/node_modules/file13.js +5 -0
  105. package/test/fixtures/eval/node_modules/file14.js +11 -0
  106. package/test/fixtures/eval/node_modules/file2.js +5 -0
  107. package/test/fixtures/eval/node_modules/file3.js +5 -0
  108. package/test/fixtures/eval/node_modules/file4.js +5 -0
  109. package/test/fixtures/eval/node_modules/file5.js +5 -0
  110. package/test/fixtures/eval/node_modules/file6.js +5 -0
  111. package/test/fixtures/eval/node_modules/file7.js +5 -0
  112. package/test/fixtures/eval/node_modules/file8.js +5 -0
  113. package/test/fixtures/eval/node_modules/file9.js +5 -0
  114. package/test/fixtures/noop-transport.js +10 -0
  115. package/test/fixtures/pretty/null-prototype.js +8 -0
  116. package/test/fixtures/stdout-hack-protection.js +11 -0
  117. package/test/fixtures/syncfalse-child.js +6 -0
  118. package/test/fixtures/syncfalse-exit.js +9 -0
  119. package/test/fixtures/syncfalse-flush-exit.js +10 -0
  120. package/test/fixtures/syncfalse.js +6 -0
  121. package/test/fixtures/syntax-error-esm.mjs +2 -0
  122. package/test/fixtures/to-file-transport-with-transform.js +20 -0
  123. package/test/fixtures/to-file-transport.js +13 -0
  124. package/test/fixtures/to-file-transport.mjs +8 -0
  125. package/test/fixtures/transport/index.js +12 -0
  126. package/test/fixtures/transport/package.json +5 -0
  127. package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
  128. package/test/fixtures/transport-exit-immediately.js +11 -0
  129. package/test/fixtures/transport-exit-on-ready.js +12 -0
  130. package/test/fixtures/transport-invalid-node-options.js +26 -0
  131. package/test/fixtures/transport-main.js +9 -0
  132. package/test/fixtures/transport-many-lines.js +29 -0
  133. package/test/fixtures/transport-preload-main.mjs +13 -0
  134. package/test/fixtures/transport-preload.mjs +13 -0
  135. package/test/fixtures/transport-string-stdout.js +9 -0
  136. package/test/fixtures/transport-transform.js +21 -0
  137. package/test/fixtures/transport-uses-pino-config.js +33 -0
  138. package/test/fixtures/transport-with-on-exit.js +12 -0
  139. package/test/fixtures/transport-worker-data.js +19 -0
  140. package/test/fixtures/transport-worker-name.js +24 -0
  141. package/test/fixtures/transport-worker.js +15 -0
  142. package/test/fixtures/transport-wrong-export-type.js +3 -0
  143. package/test/fixtures/ts/to-file-transport-native.mts +15 -0
  144. package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
  145. package/test/fixtures/ts/to-file-transport.ts +11 -0
  146. package/test/fixtures/ts/transpile.cjs +36 -0
  147. package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
  148. package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
  149. package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
  150. package/test/fixtures/ts/transport-main.ts +8 -0
  151. package/test/fixtures/ts/transport-string-stdout.ts +8 -0
  152. package/test/fixtures/ts/transport-worker.ts +14 -0
  153. package/test/formatters.test.js +364 -0
  154. package/test/helper.d.ts +4 -0
  155. package/test/helper.js +155 -0
  156. package/test/hooks.test.js +114 -0
  157. package/test/http.test.js +214 -0
  158. package/test/internals/version.test.js +17 -0
  159. package/test/is-level-enabled.test.js +179 -0
  160. package/test/jest/basic.spec.js +10 -0
  161. package/test/levels.test.js +810 -0
  162. package/test/metadata.test.js +120 -0
  163. package/test/mixin-merge-strategy.test.js +57 -0
  164. package/test/mixin.test.js +241 -0
  165. package/test/multistream.test.js +729 -0
  166. package/test/redact.test.js +893 -0
  167. package/test/serializers.test.js +257 -0
  168. package/test/stdout-protection.test.js +41 -0
  169. package/test/syncfalse.test.js +186 -0
  170. package/test/timestamp-nano.test.js +37 -0
  171. package/test/timestamp.test.js +124 -0
  172. package/test/transport/big.test.js +42 -0
  173. package/test/transport/bundlers-support.test.js +99 -0
  174. package/test/transport/caller.test.js +24 -0
  175. package/test/transport/core.test.js +733 -0
  176. package/test/transport/core.transpiled.test.ts +114 -0
  177. package/test/transport/crash.test.js +36 -0
  178. package/test/transport/module-link.test.js +241 -0
  179. package/test/transport/native-type-stripping.test.mjs +151 -0
  180. package/test/transport/node-options.test.js +116 -0
  181. package/test/transport/pipeline.test.js +137 -0
  182. package/test/transport/preload.test.js +54 -0
  183. package/test/transport/repl.test.js +15 -0
  184. package/test/transport/sync-false.test.js +67 -0
  185. package/test/transport/sync-true.test.js +57 -0
  186. package/test/transport/targets.test.js +48 -0
  187. package/test/transport/uses-pino-config.test.js +166 -0
  188. package/test/transport-stream.test.js +40 -0
  189. package/test/types/pino-import.test-d.cts +30 -0
  190. package/test/types/pino-multistream.test-d.ts +28 -0
  191. package/test/types/pino-top-export.test-d.ts +34 -0
  192. package/test/types/pino-transport.test-d.ts +156 -0
  193. package/test/types/pino-type-only.test-d.ts +75 -0
  194. package/test/types/pino.test-d.ts +683 -0
  195. package/test/types/pino.ts +91 -0
  196. 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
+ })