UNPKG

pino

Version:

super fast, all natural json logger

356 lines (332 loc) 7.13 kB
'use strict' /* eslint no-prototype-builtins: 0 */ const { hostname } = require('node:os') const { join } = require('node:path') const { readFile } = require('node:fs').promises const { test } = require('tap') const { sink, once, watchFileCreated, file } = require('./helper') const pino = require('../') test('level formatter', async ({ match }) => { const stream = sink() const logger = pino({ formatters: { level (label, number) { return { log: { level: label } } } } }, stream) const o = once(stream, 'data') logger.info('hello world') match(await o, { log: { level: 'info' } }) }) test('bindings formatter', async ({ match }) => { const stream = sink() const logger = pino({ formatters: { bindings (bindings) { return { process: { pid: bindings.pid }, host: { name: bindings.hostname } } } } }, stream) const o = once(stream, 'data') logger.info('hello world') match(await o, { process: { pid: process.pid }, host: { name: hostname() } }) }) test('no bindings formatter', async ({ match, notOk }) => { const stream = sink() const logger = pino({ formatters: { bindings (bindings) { return null } } }, stream) const o = once(stream, 'data') logger.info('hello world') const log = await o notOk(log.hasOwnProperty('pid')) notOk(log.hasOwnProperty('hostname')) match(log, { msg: 'hello world' }) }) test('log formatter', async ({ match, equal }) => { const stream = sink() const logger = pino({ formatters: { log (obj) { equal(obj.hasOwnProperty('msg'), false) return { hello: 'world', ...obj } } } }, stream) const o = once(stream, 'data') logger.info({ foo: 'bar', nested: { object: true } }, 'hello world') match(await o, { hello: 'world', foo: 'bar', nested: { object: true } }) }) test('Formatters combined', async ({ match }) => { const stream = sink() const logger = pino({ formatters: { level (label, number) { return { log: { level: label } } }, bindings (bindings) { return { process: { pid: bindings.pid }, host: { name: bindings.hostname } } }, log (obj) { return { hello: 'world', ...obj } } } }, stream) const o = once(stream, 'data') logger.info({ foo: 'bar', nested: { object: true } }, 'hello world') match(await o, { log: { level: 'info' }, process: { pid: process.pid }, host: { name: hostname() }, hello: 'world', foo: 'bar', nested: { object: true } }) }) test('Formatters in child logger', async ({ match }) => { const stream = sink() const logger = pino({ formatters: { level (label, number) { return { log: { level: label } } }, bindings (bindings) { return { process: { pid: bindings.pid }, host: { name: bindings.hostname } } }, log (obj) { return { hello: 'world', ...obj } } } }, stream) const child = logger.child({ foo: 'bar', nested: { object: true } }, { formatters: { bindings (bindings) { return { ...bindings, faz: 'baz' } } } }) const o = once(stream, 'data') child.info('hello world') match(await o, { log: { level: 'info' }, process: { pid: process.pid }, host: { name: hostname() }, hello: 'world', foo: 'bar', nested: { object: true }, faz: 'baz' }) }) test('Formatters without bindings in child logger', async ({ match }) => { const stream = sink() const logger = pino({ formatters: { level (label, number) { return { log: { level: label } } }, bindings (bindings) { return { process: { pid: bindings.pid }, host: { name: bindings.hostname } } }, log (obj) { return { hello: 'world', ...obj } } } }, stream) const child = logger.child({ foo: 'bar', nested: { object: true } }, { formatters: { log (obj) { return { other: 'stuff', ...obj } } } }) const o = once(stream, 'data') child.info('hello world') match(await o, { log: { level: 'info' }, process: { pid: process.pid }, host: { name: hostname() }, foo: 'bar', other: 'stuff', nested: { object: true } }) }) test('elastic common schema format', async ({ match, type }) => { const stream = sink() const ecs = { formatters: { level (label, number) { return { log: { level: label, logger: 'pino' } } }, bindings (bindings) { return { process: { pid: bindings.pid }, host: { name: bindings.hostname } } }, log (obj) { return { ecs: { version: '1.4.0' }, ...obj } } }, messageKey: 'message', timestamp: () => `,"@timestamp":"${new Date(Date.now()).toISOString()}"` } const logger = pino({ ...ecs }, stream) const o = once(stream, 'data') logger.info({ foo: 'bar' }, 'hello world') const log = await o type(log['@timestamp'], 'string') match(log, { log: { level: 'info', logger: 'pino' }, process: { pid: process.pid }, host: { name: hostname() }, ecs: { version: '1.4.0' }, foo: 'bar', message: 'hello world' }) }) test('formatter with transport', async ({ match, equal }) => { const destination = file() const logger = pino({ formatters: { log (obj) { equal(obj.hasOwnProperty('msg'), false) return { hello: 'world', ...obj } } }, transport: { targets: [ { target: join(__dirname, 'fixtures', 'to-file-transport.js'), options: { destination } } ] } }) logger.info({ foo: 'bar', nested: { object: true } }, 'hello world') await watchFileCreated(destination) const result = JSON.parse(await readFile(destination)) delete result.time match(result, { hello: 'world', foo: 'bar', nested: { object: true } }) }) test('throws when custom level formatter is used with transport.targets', async ({ throws }) => { throws(() => { pino({ formatters: { level (label) { return label } }, transport: { targets: [ { target: 'pino/file', options: { destination: 'foo.log' } } ] } } ) }, Error('option.transport.targets do not allow custom level formatters')) })