pinojs / pino

🌲 super fast, all natural json logger
http://getpino.io
MIT License
14.21k stars 875 forks source link

What is the difference between multiple transports and pino.multistream()? #1514

Closed dlcoffee closed 1 year ago

dlcoffee commented 2 years ago

i'm a new pino user and i'm trying to figure out what the correct pino apis to use are. my use case is that i'd like to be able to to log to the console as well as a file. it seems like i can do it two ways:

  1. using multiple transport targets

    const pino = require('pino')
    const transports = pino.transport({
    targets: [{
    level: 'info',
    target: 'pino/file'
    }, {
    level: 'trace',
    target: 'pino/file',
    options: { destination: '/path/to/store/logs' }
    }]
    })
    const logger = pino(transports)
  2. using multistream

    
    const pino = require('pino')
    const streams = [
    { stream: pino.destination(1) },
    { stream: fs.createWriteStream('/path/to/store/logs') }, // is this not recommended?
    { stream: pino.destination({ dest: '/path/to/store/logs2' }) },
    ]

const logger = pino( { level: 'trace', }, pino.multistream(streams) )



what's the recommended approach in this instance? it seems like both apis are async by default (https://github.com/pinojs/pino/issues/1260#issuecomment-989147012), so i can't tell why i'd use one over the other.

i also noticed that the documentation recommends that it is strongly recommended to use `pino.destination()` over `fs.createWriteStream` (https://getpino.io/#/docs/api?id=destination-sonicboom-writablestream-string-object), but the majority of the examples are using `createWriteStream()`. do the docs need to be updated? if so, i can try to tackle that to make it less confusing.

> An ordinary Node.js stream can be passed as the destination (such as the result of fs.createWriteStream) but for peak log writing performance it is strongly recommended to use pino.destination to create the destination stream.

lastly, i'm a bit confused as to why `pino-multi-stream` got embedded into the main `pino` library. based on their docs, it seemed like it was only meant to be a stop-gap for migration from another logger library: https://github.com/pinojs/pino-multi-stream#caveats

> **Stern warning**: the performance of this module being dependent on the number of streams you supply cannot be overstated. This module is being provided so that you can switch to pino from Bunyan and get some immediate improvement, but it is not meant to be a long term solution.

a similar warning appears in the `pino` docs as well: https://getpino.io/#/docs/help?id=multi-stream

> While not recommended for performance reasons, multiple destinations can be targeted by using [pino.multistream](https://getpino.io/#/doc/api?id=pino-multistream).

to summarize:

1. is there a reason why i would choose `pino.multistream()` over multiple `transport` targets?
2. do the examples in the documentation need to be updated to use more `pino.destination()` over `fs.createWriteStream()`
3. (a bit related to 1) is the performance warning around `pino.multistream` still relevant since it is async by default?
mcollina commented 2 years ago

is there a reason why i would choose pino.multistream() over multiple transport targets?

transports works off the main thread. This has some consequences - ideally better performance. However there might be edge cases where you need to be in-thread. Generically, use transports.

do the examples in the documentation need to be updated to use more pino.destination() over fs.createWriteStream()

Possibly, would you like to send a PR?

(a bit related to 1) is the performance warning around pino.multistream still relevant since it is async by default?

Writing to multiple destinations adds overhead and latency. It's simply more work to do for your process. Doing it inside the main thread will increase the latency of your HTTP responses.

dlcoffee commented 2 years ago

hmm, okay maybe it is my misunderstanding that multistream being asynchronous is not the same as it working off the main thread. it's still on the main thread, but it only buffers the messages and writes them in chunks.

mayeaux commented 1 year ago

Lmao obviously this is the use case for virtually anyone in a dev environment and yet there is virtually no documentation on how to do it, ChatGPT can't do it, there's no examples on Stackoverflow, amazing

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.