pinojs/pino

Verifying logs from unit tests (again!)

Closed this issue · 6 comments

Hello,

I've been trying to verify log records in unit tests, and thought I would share my solution. I realise this has been discussed before (#1274), however the proposed solution was incomplete, and I suspect will no longer work due to serialisation issues inherent with worker threads (#1786).

Instead, the approach I've taken is to transmit data from the worker to the parent via postMessage as described in #1343. This works because the transport is an instance of ThreadStream and providing the postMessage data is in the correct format, it will be re-emitted as a regular node event.

Here's the code...

// logger.js
const { join, resolve } = require('node:path');
const pino = require('pino');

const targets = [{
  target: 'pino/file',
  options: { destination: 1 }
}, {
  target: resolve('post-message-transport')
}];

const transport = pino.transport({
  targets
});

const logger = pino({
  base: null, // Exclude pid and hostname
}, transport);

// Forward 'message' events from the transport to the logger
transport.on('message', (...args) => {
  logger.emit('message', ...args);
})

module.exports = logger;
// post-message-transport.js
const { parentPort } = require("node:worker_threads");
const build = require('pino-abstract-transport');

module.exports = function() {
  return build(function(source) {
    source.on('data', function(record) {
      // code: 'EVENT' is required by ThreadStream
      // name: 'message' determines the event name
      parentPort.postMessage({ code: 'EVENT', name: 'message', args: [record]});
    })
  })
}
// my.test.js
const { strictEqual: eq, deepStrictEqual: deq } = require('node:assert');
const { describe, it } = require('zunit');
const logger = require('../logger');

it('should verify logs', (t, done) => {
  logger.once('message', (record) => {
    eq(record.msg, 'Some message')
    eq(record.foo, 'bar')
    done();
  });
  logger.info({ foo: 'bar' }, 'Some message');
})

nice! I think it might be a good addition to the new https://www.npmjs.com/package/pino-test

Thanks. I wasn't aware of pino-test. I'll take and see if I can work out where it fits in. Guessing from a brief look, the idea would be to add the post-message-transport.js, update the README and add some tests?

yes exactly

Sorry closed prematurely.

Looking at pino-test, I'm not sure how I would make the post-message-transport accessible in a way it could be resolved by pino.

If I understand correctly, pino either requires an absolute path, or the module name for the target. Assuming I'm right, wouldn't it be simpler if I publish the post-message-transport as its own module? Or maybe there's something I'm missing?

yes that would also be ok.

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.