Skip to content

Commit 5bc0a92

Browse files
authored
feature: allow sync flag to be passed to ThreadStream for synchronous… (#2063)
* feature: allow sync flag to be passed to ThreadStream for synchronous logging * tests: add unit tests for sync true to ThreadStream * tests: fix unit test * tests: fix unit test
1 parent f220965 commit 5bc0a92

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

docs/transports.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ now referred to as [Legacy Transports](#legacy-transports).
1515

1616
From Pino v7 and upwards transports can also operate inside a [Worker Thread][worker-thread]
1717
and can be used or configured via the options object passed to `pino` on initialization.
18-
In this case the transports would always operate asynchronously, and logs would be
18+
In this case the transports would always operate asynchronously (unless `options.sync` is set to `true` in transport options), and logs would be
1919
flushed as quickly as possible (there is nothing to do).
2020

2121
[worker-thread]: https://nodejs.org/dist/latest-v14.x/docs/api/worker_threads.html
@@ -124,6 +124,19 @@ const transport = pino.transport({
124124
pino(transport)
125125
```
126126
127+
To make pino log synchronously, pass `sync: true` to transport options.
128+
```js
129+
const pino = require('pino')
130+
const transport = pino.transport({
131+
targets: [
132+
{ target: '/absolute/path/to/my-transport.mjs', level: 'error' },
133+
],
134+
dedupe: true,
135+
sync: true,
136+
});
137+
pino(transport);
138+
```
139+
127140
For more details on `pino.transport` see the [API docs for `pino.transport`][pino-transport].
128141
129142
[pino-transport]: /docs/api.md#pino-transport

lib/transport.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ function setupOnExit (stream) {
1717
})
1818
}
1919

20-
function buildStream (filename, workerData, workerOpts) {
20+
function buildStream (filename, workerData, workerOpts, sync) {
2121
const stream = new ThreadStream({
2222
filename,
2323
workerData,
24-
workerOpts
24+
workerOpts,
25+
sync
2526
})
2627

2728
stream.on('ready', onReady)
@@ -71,7 +72,7 @@ function flush (stream) {
7172
}
7273

7374
function transport (fullOptions) {
74-
const { pipeline, targets, levels, dedupe, worker = {}, caller = getCallers() } = fullOptions
75+
const { pipeline, targets, levels, dedupe, worker = {}, caller = getCallers(), sync = false } = fullOptions
7576

7677
const options = {
7778
...fullOptions.options
@@ -126,7 +127,7 @@ function transport (fullOptions) {
126127

127128
options.pinoWillSendConfig = true
128129

129-
return buildStream(fixTarget(target), options, worker)
130+
return buildStream(fixTarget(target), options, worker, sync)
130131

131132
function fixTarget (origin) {
132133
origin = bundlerOverrides[origin] || origin

test/transport/syncTrue.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict'
2+
3+
const pino = require('../..')
4+
const { join } = require('node:path')
5+
const { readFileSync } = require('node:fs')
6+
const { test } = require('tap')
7+
const { file } = require('../helper')
8+
9+
test('thread-stream sync true should log synchronously', async (t) => {
10+
const outputPath = file()
11+
12+
function getOutputLogLines () {
13+
return (readFileSync(outputPath)).toString().trim().split('\n').map(JSON.parse)
14+
}
15+
16+
const transport = pino.transport({
17+
target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
18+
options: { destination: outputPath, flush: true },
19+
sync: true
20+
})
21+
const instance = pino(transport)
22+
23+
var value = { message: 'sync' }
24+
instance.info(value)
25+
instance.info(value)
26+
instance.info(value)
27+
instance.info(value)
28+
instance.info(value)
29+
instance.info(value)
30+
let interrupt = false
31+
let flushData
32+
let loopCounter = 0
33+
34+
// Start a synchronous loop
35+
while (!interrupt && loopCounter < (process.env.MAX_TEST_LOOP_ITERATION || 20000)) {
36+
try {
37+
loopCounter++
38+
const data = getOutputLogLines()
39+
flushData = data
40+
if (data) {
41+
interrupt = true
42+
break
43+
}
44+
} catch (error) {
45+
// File may not exist yet
46+
// Wait till MAX_TEST_LOOP_ITERATION iterations
47+
}
48+
}
49+
50+
if (!interrupt) {
51+
throw new Error('Sync loop did not get interrupt')
52+
}
53+
54+
t.equal(flushData.length, 6)
55+
})

0 commit comments

Comments
 (0)