diff --git a/docs/transports.md b/docs/transports.md index 1acc5451f..bafb853f3 100644 --- a/docs/transports.md +++ b/docs/transports.md @@ -251,6 +251,17 @@ const transport = pino.transport({ pino(transport) ``` +By default, the `pino/file` transport appends to the destination file if it exists. The `append` option may be set to `false` to configure the transport to truncate the file upon opening it for writing. + +```js +const pino = require('pino') +const transport = pino.transport({ + target: 'pino/file', + options: { destination: '/path/to/file', append: false } +}) +pino(transport) +``` + The `options.destination` property may also be a number to represent a file descriptor. Typically this would be `1` to write to STDOUT or `2` to write to STDERR. If `options.destination` is not set, it defaults to `1` which means logs will be written to STDOUT. The difference between using the `pino/file` transport builtin and using `pino.destination` is that `pino.destination` runs in the main thread, whereas `pino/file` sets up `pino.destination` in a worker thread. diff --git a/file.js b/file.js index a75366164..eade8cd90 100644 --- a/file.js +++ b/file.js @@ -5,6 +5,7 @@ const { once } = require('events') module.exports = async function (opts = {}) { const destOpts = { dest: opts.destination || 1, sync: false } + if (opts.append === false) destOpts.append = false if (opts.mkdir) destOpts.mkdir = true const destination = pino.destination(destOpts) await once(destination, 'ready') diff --git a/test/helper.js b/test/helper.js index e57419f86..0b3a95e93 100644 --- a/test/helper.js +++ b/test/helper.js @@ -3,7 +3,7 @@ const os = require('os') const writer = require('flush-write-stream') const split = require('split2') -const { existsSync, statSync } = require('fs') +const { existsSync, readFileSync, statSync } = require('fs') const pid = process.pid const hostname = os.hostname() @@ -77,4 +77,24 @@ function watchFileCreated (filename) { }) } -module.exports = { getPathToNull, sink, check, once, sleep, watchFileCreated, isWin, isYarnPnp } +function watchForWrite (filename, testString) { + return new Promise((resolve, reject) => { + const TIMEOUT = 2000 + const INTERVAL = 100 + const threshold = TIMEOUT / INTERVAL + let counter = 0 + const interval = setInterval(() => { + if (readFileSync(filename).includes(testString)) { + clearInterval(interval) + resolve() + } else if (counter <= threshold) { + counter++ + } else { + clearInterval(interval) + reject(new Error(`'${testString}' hasn't been written to ${filename} within ${TIMEOUT} ms.`)) + } + }, INTERVAL) + }) +} + +module.exports = { getPathToNull, sink, check, once, sleep, watchFileCreated, watchForWrite, isWin, isYarnPnp } diff --git a/test/transport/core.test.js b/test/transport/core.test.js index a08e98e7a..01da9db64 100644 --- a/test/transport/core.test.js +++ b/test/transport/core.test.js @@ -3,8 +3,8 @@ const os = require('os') const { join } = require('path') const { once } = require('events') -const { readFile } = require('fs').promises -const { watchFileCreated } = require('../helper') +const { readFile, writeFile } = require('fs').promises +const { watchFileCreated, watchForWrite } = require('../helper') const { test } = require('tap') const pino = require('../../') const url = require('url') @@ -300,6 +300,30 @@ test('pino.transport with target pino/file and mkdir option', async ({ same, tea }) }) +test('pino.transport with target pino/file and append option', async ({ same, teardown }) => { + const destination = join( + os.tmpdir(), + '_' + Math.random().toString(36).substr(2, 9) + ) + await writeFile(destination, JSON.stringify({ pid, hostname, time: Date.now(), level: 30, msg: 'hello' })) + const transport = pino.transport({ + target: 'pino/file', + options: { destination, append: false } + }) + teardown(transport.end.bind(transport)) + const instance = pino(transport) + instance.info('goodbye') + await watchForWrite(destination, '"goodbye"') + const result = JSON.parse(await readFile(destination)) + delete result.time + same(result, { + pid, + hostname, + level: 30, + msg: 'goodbye' + }) +}) + test('pino.transport with target pino-pretty', async ({ match, teardown }) => { const destination = join( os.tmpdir(),