Reputation: 15248
from what I understand, Pino (v 7.5.1) by default does sync logging. From the docs
In Pino's standard mode of operation log messages are directly written to the output stream as the messages are generated with a blocking operation.
I am using pino.multistreams
like so
const pino = require('pino')
const pretty = require('pino-pretty')
const logdir = '/Users/punkish/Projects/z/logs'
const streams = [
{stream: fs.createWriteStream(`${logdir}/info.log`, {flags: 'a'})},
{stream: pretty()},
{level: 'error', stream: fs.createWriteStream(`${logdir}/error.log`, {flags: 'a'})},
{level: 'debug', stream: fs.createWriteStream(`${logdir}/debug.log`, {flags: 'a'})},
{level: 'fatal', stream: fs.createWriteStream(`${logdir}/fatal.log`, {flags: 'a'})}
]
Strangely, Pino is behaving asynchronously. I have a curl
operation that is outputting out of sequence (before earlier events that are using log.info
)
log.info('1')
.. code to do 1 something
log.info('2')
.. code to do 2 something
log.info('3')
.. code to do 3 something
const execSync = require('child_process').execSync
execSync(curl --silent --output ${local} '${remote}')
and my console
output is
1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 39.5M 100 39.5M 0 0 108M 0 --:--:-- --:--:-- --:--:-- 113M
2
3
this is a bit annoying and confusing. Maybe this is not the fault of Pino, and maybe curl
is causing the problem. But if I replace pino logging with console.log
then the order is as expected. So it seems the problem is with Pino behaving asynchronously. How can I go back to synchronous logging?
Upvotes: 6
Views: 8022
Reputation: 43
The most upvoted solution does not work if you have a custom DestinationStream
as SonicBoom will only work with files and file descriptors
Error: SonicBoom supports only file descriptors and files
Upvotes: 0
Reputation: 4525
The trick is to call pino.destination({...})
to create a SonicBoom output stream: a pino-specific alternative to fs.createWriteStream
. The SonicBoom
options have a boolean property sync
. You also need the sync
option in pretty({...})
.
const pino = require('pino')
const pretty = require('pino-pretty')
const logdir = '/Users/punkish/Projects/z/logs'
const createSonicBoom = (dest) =>
pino.destination({dest: dest, append: true, sync: true})
const streams = [
{stream: createSonicBoom(`${logdir}/info.log`)},
{stream: pretty({
colorize: true,
sync: true,
})},
{level: 'error', stream: createSonicBoom(`${logdir}/error.log`)},
{level: 'debug', stream: createSonicBoom(`${logdir}/debug.log`)},
{level: 'fatal', stream: createSonicBoom(`${logdir}/fatal.log`)}
]
Test:
const log = pino({ level: 'info' }, pino.multistream(streams))
console.log('Before-Fatal')
log.fatal('Fatal')
log.error('Error')
log.warn('Warn')
console.log('After-Warn, Before-Info')
log.info('Info')
console.log('After-Info')
Output:
Before-Fatal [1234567890123] FATAL (1234567 on host): Fatal [1234567890127] ERROR (1234567 on host): Error [1234567890127] WARN (1234567 on host): Warn After-Warn, Before-Info [1234567890128] INFO (1234567 on host): Info After-Info
Upvotes: 5
Reputation: 15248
seems like using pino.multistream
(or multiple transports, which seem to have the same effect as multistream) automatically forces pino to behave asynchronously. There is no way around it. Since synchronous logging is more impt for me than speed (in this project), I will look for an alternative logging solution
Upvotes: 1