Buckets:
| const { describe, test } = require('node:test') | |
| const assert = require('node:assert') | |
| const tspl = require('@matteo.collina/tspl') | |
| const { sink, once, check } = require('./helper') | |
| const pino = require('../') | |
| const levelsLib = require('../lib/levels') | |
| // Silence all warnings for this test | |
| process.removeAllListeners('warning') | |
| process.on('warning', () => {}) | |
| test('set the level by string', async () => { | |
| const expected = [{ | |
| level: 50, | |
| msg: 'this is an error' | |
| }, { | |
| level: 60, | |
| msg: 'this is fatal' | |
| }] | |
| const stream = sink() | |
| const instance = pino(stream) | |
| instance.level = 'error' | |
| instance.info('hello world') | |
| instance.error('this is an error') | |
| instance.fatal('this is fatal') | |
| const result = await once(stream, 'data') | |
| const current = expected.shift() | |
| check(assert.equal, result, current.level, current.msg) | |
| }) | |
| test('the wrong level throws', async () => { | |
| const instance = pino() | |
| assert.throws(() => { | |
| instance.level = 'kaboom' | |
| }) | |
| }) | |
| test('set the level by number', async () => { | |
| const expected = [{ | |
| level: 50, | |
| msg: 'this is an error' | |
| }, { | |
| level: 60, | |
| msg: 'this is fatal' | |
| }] | |
| const stream = sink() | |
| const instance = pino(stream) | |
| instance.level = 50 | |
| instance.info('hello world') | |
| instance.error('this is an error') | |
| instance.fatal('this is fatal') | |
| const result = await once(stream, 'data') | |
| const current = expected.shift() | |
| check(assert.equal, result, current.level, current.msg) | |
| }) | |
| test('exposes level string mappings', async () => { | |
| assert.equal(pino.levels.values.error, 50) | |
| }) | |
| test('exposes level number mappings', async () => { | |
| assert.equal(pino.levels.labels[50], 'error') | |
| }) | |
| test('returns level integer', async () => { | |
| const instance = pino({ level: 'error' }) | |
| assert.equal(instance.levelVal, 50) | |
| }) | |
| test('child returns level integer', async () => { | |
| const parent = pino({ level: 'error' }) | |
| const child = parent.child({ foo: 'bar' }) | |
| assert.equal(child.levelVal, 50) | |
| }) | |
| test('set the level via exported pino function', async () => { | |
| const expected = [{ | |
| level: 50, | |
| msg: 'this is an error' | |
| }, { | |
| level: 60, | |
| msg: 'this is fatal' | |
| }] | |
| const stream = sink() | |
| const instance = pino({ level: 'error' }, stream) | |
| instance.info('hello world') | |
| instance.error('this is an error') | |
| instance.fatal('this is fatal') | |
| const result = await once(stream, 'data') | |
| const current = expected.shift() | |
| check(assert.equal, result, current.level, current.msg) | |
| }) | |
| test('level-change event', async (t) => { | |
| const plan = tspl(t, { plan: 8 }) | |
| const instance = pino() | |
| function handle (lvl, val, prevLvl, prevVal, logger) { | |
| plan.equal(lvl, 'trace') | |
| plan.equal(val, 10) | |
| plan.equal(prevLvl, 'info') | |
| plan.equal(prevVal, 30) | |
| plan.equal(logger, instance) | |
| } | |
| instance.on('level-change', handle) | |
| instance.level = 'trace' | |
| instance.removeListener('level-change', handle) | |
| instance.level = 'info' | |
| let count = 0 | |
| const l1 = () => count++ | |
| const l2 = () => count++ | |
| const l3 = () => count++ | |
| instance.on('level-change', l1) | |
| instance.on('level-change', l2) | |
| instance.on('level-change', l3) | |
| instance.level = 'trace' | |
| instance.removeListener('level-change', l3) | |
| instance.level = 'fatal' | |
| instance.removeListener('level-change', l1) | |
| instance.level = 'debug' | |
| instance.removeListener('level-change', l2) | |
| instance.level = 'info' | |
| plan.equal(count, 6) | |
| instance.once('level-change', (lvl, val, prevLvl, prevVal, logger) => plan.equal(logger, instance)) | |
| instance.level = 'info' | |
| const child = instance.child({}) | |
| instance.once('level-change', (lvl, val, prevLvl, prevVal, logger) => plan.equal(logger, child)) | |
| child.level = 'trace' | |
| await plan | |
| }) | |
| test('enable', async (t) => { | |
| const instance = pino({ | |
| level: 'trace', | |
| enabled: false | |
| }, sink((result, enc) => { | |
| throw Error('no data should be logged') | |
| })) | |
| Object.keys(pino.levels.values).forEach((level) => { | |
| instance[level]('hello world') | |
| }) | |
| }) | |
| test('silent level', async () => { | |
| const instance = pino({ | |
| level: 'silent' | |
| }, sink((result, enc) => { | |
| throw Error('no data should be logged') | |
| })) | |
| Object.keys(pino.levels.values).forEach((level) => { | |
| instance[level]('hello world') | |
| }) | |
| }) | |
| test('set silent via Infinity', async () => { | |
| const instance = pino({ | |
| level: Infinity | |
| }, sink((result, enc) => { | |
| throw Error('no data should be logged') | |
| })) | |
| Object.keys(pino.levels.values).forEach((level) => { | |
| instance[level]('hello world') | |
| }) | |
| }) | |
| test('exposed levels', async () => { | |
| assert.deepEqual(Object.keys(pino.levels.values), [ | |
| 'trace', | |
| 'debug', | |
| 'info', | |
| 'warn', | |
| 'error', | |
| 'fatal' | |
| ]) | |
| }) | |
| test('exposed labels', async () => { | |
| assert.deepEqual(Object.keys(pino.levels.labels), [ | |
| '10', | |
| '20', | |
| '30', | |
| '40', | |
| '50', | |
| '60' | |
| ]) | |
| }) | |
| test('setting level in child', async (t) => { | |
| const plan = tspl(t, { plan: 10 }) | |
| const expected = [{ | |
| level: 50, | |
| msg: 'this is an error' | |
| }, { | |
| level: 60, | |
| msg: 'this is fatal' | |
| }] | |
| const instance = pino(sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| check(plan.equal, result, current.level, current.msg) | |
| cb() | |
| })).child({ level: 30 }) | |
| instance.level = 'error' | |
| instance.info('hello world') | |
| instance.error('this is an error') | |
| instance.fatal('this is fatal') | |
| await plan | |
| }) | |
| test('setting level by assigning a number to level', async () => { | |
| const instance = pino() | |
| assert.equal(instance.levelVal, 30) | |
| assert.equal(instance.level, 'info') | |
| instance.level = 50 | |
| assert.equal(instance.levelVal, 50) | |
| assert.equal(instance.level, 'error') | |
| }) | |
| test('setting level by number to unknown value results in a throw', async () => { | |
| const instance = pino() | |
| assert.throws(() => { instance.level = 973 }) | |
| }) | |
| test('setting level by assigning a known label to level', async () => { | |
| const instance = pino() | |
| assert.equal(instance.levelVal, 30) | |
| assert.equal(instance.level, 'info') | |
| instance.level = 'error' | |
| assert.equal(instance.levelVal, 50) | |
| assert.equal(instance.level, 'error') | |
| }) | |
| test('levelVal is read only', async () => { | |
| const instance = pino() | |
| assert.throws(() => { instance.levelVal = 20 }) | |
| }) | |
| test('produces labels when told to', async (t) => { | |
| const plan = tspl(t, { plan: 5 }) | |
| const expected = [{ | |
| level: 'info', | |
| msg: 'hello world' | |
| }] | |
| const instance = pino({ | |
| formatters: { | |
| level (label, number) { | |
| return { level: label } | |
| } | |
| } | |
| }, sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| check(plan.equal, result, current.level, current.msg) | |
| cb() | |
| })) | |
| instance.info('hello world') | |
| await plan | |
| }) | |
| test('resets levels from labels to numbers', async (t) => { | |
| const plan = tspl(t, { plan: 5 }) | |
| const expected = [{ | |
| level: 30, | |
| msg: 'hello world' | |
| }] | |
| pino({ useLevelLabels: true }) | |
| const instance = pino({ useLevelLabels: false }, sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| check(plan.equal, result, current.level, current.msg) | |
| cb() | |
| })) | |
| instance.info('hello world') | |
| await plan | |
| }) | |
| test('changes label naming when told to', async (t) => { | |
| const plan = tspl(t, { plan: 2 }) | |
| const expected = [{ | |
| priority: 30, | |
| msg: 'hello world' | |
| }] | |
| const instance = pino({ | |
| formatters: { | |
| level (label, number) { | |
| return { priority: number } | |
| } | |
| } | |
| }, sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| plan.equal(result.priority, current.priority) | |
| plan.equal(result.msg, current.msg) | |
| cb() | |
| })) | |
| instance.info('hello world') | |
| await plan | |
| }) | |
| test('children produce labels when told to', async (t) => { | |
| const plan = tspl(t, { plan: 10 }) | |
| const expected = [ | |
| { | |
| level: 'info', | |
| msg: 'child 1' | |
| }, | |
| { | |
| level: 'info', | |
| msg: 'child 2' | |
| } | |
| ] | |
| const instance = pino({ | |
| formatters: { | |
| level (label, number) { | |
| return { level: label } | |
| } | |
| } | |
| }, sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| check(plan.equal, result, current.level, current.msg) | |
| cb() | |
| })) | |
| const child1 = instance.child({ name: 'child1' }) | |
| const child2 = child1.child({ name: 'child2' }) | |
| child1.info('child 1') | |
| child2.info('child 2') | |
| await plan | |
| }) | |
| test('produces labels for custom levels', async (t) => { | |
| const plan = tspl(t, { plan: 10 }) | |
| const expected = [ | |
| { | |
| level: 'info', | |
| msg: 'hello world' | |
| }, | |
| { | |
| level: 'foo', | |
| msg: 'foobar' | |
| } | |
| ] | |
| const opts = { | |
| formatters: { | |
| level (label, number) { | |
| return { level: label } | |
| } | |
| }, | |
| customLevels: { | |
| foo: 35 | |
| } | |
| } | |
| const instance = pino(opts, sink((result, enc, cb) => { | |
| const current = expected.shift() | |
| check(plan.equal, result, current.level, current.msg) | |
| cb() | |
| })) | |
| instance.info('hello world') | |
| instance.foo('foobar') | |
| await plan | |
| }) | |
| test('setting levelKey does not affect labels when told to', async (t) => { | |
| const plan = tspl(t, { plan: 1 }) | |
| const instance = pino( | |
| { | |
| formatters: { | |
| level (label, number) { | |
| return { priority: label } | |
| } | |
| } | |
| }, | |
| sink((result, enc, cb) => { | |
| plan.equal(result.priority, 'info') | |
| cb() | |
| }) | |
| ) | |
| instance.info('hello world') | |
| await plan | |
| }) | |
| test('throws when creating a default label that does not exist in logger levels', async () => { | |
| const defaultLevel = 'foo' | |
| assert.throws( | |
| () => { | |
| pino({ | |
| customLevels: { | |
| bar: 5 | |
| }, | |
| level: defaultLevel | |
| }) | |
| }, | |
| Error(`default level:${defaultLevel} must be included in custom levels`) | |
| ) | |
| }) | |
| test('throws when creating a default value that does not exist in logger levels', async () => { | |
| const defaultLevel = 15 | |
| assert.throws( | |
| () => { | |
| pino({ | |
| customLevels: { | |
| bar: 5 | |
| }, | |
| level: defaultLevel | |
| }) | |
| }, | |
| Error(`default level:${defaultLevel} must be included in custom levels`) | |
| ) | |
| }) | |
| test('throws when creating a default value that does not exist in logger levels', async ({ equal, throws }) => { | |
| assert.throws( | |
| () => { | |
| pino({ | |
| customLevels: { | |
| foo: 5 | |
| }, | |
| useOnlyCustomLevels: true | |
| }) | |
| }, | |
| /default level:info must be included in custom levels/ | |
| ) | |
| }) | |
| test('passes when creating a default value that exists in logger levels', async () => { | |
| pino({ | |
| level: 30 | |
| }) | |
| }) | |
| test('log null value when message is null', async () => { | |
| const expected = { | |
| msg: null, | |
| level: 30 | |
| } | |
| const stream = sink() | |
| const instance = pino(stream) | |
| instance.level = 'info' | |
| instance.info(null) | |
| const result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('formats when base param is null', async () => { | |
| const expected = { | |
| msg: 'a string', | |
| level: 30 | |
| } | |
| const stream = sink() | |
| const instance = pino(stream) | |
| instance.level = 'info' | |
| instance.info(null, 'a %s', 'string') | |
| const result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('fatal method sync-flushes the destination if sync flushing is available', async (t) => { | |
| const plan = tspl(t, { plan: 2 }) | |
| const stream = sink() | |
| stream.flushSync = () => { | |
| plan.ok('destination flushed') | |
| } | |
| const instance = pino(stream) | |
| instance.fatal('this is fatal') | |
| await once(stream, 'data') | |
| plan.doesNotThrow(() => { | |
| stream.flushSync = undefined | |
| instance.fatal('this is fatal') | |
| }) | |
| await plan | |
| }) | |
| test('fatal method should call async when sync-flushing fails', async (t) => { | |
| const plan = tspl(t, { plan: 1 }) | |
| const messages = [ | |
| 'this is fatal 1' | |
| ] | |
| const stream = sink((result) => assert.equal(result.msg, messages.shift())) | |
| stream.flushSync = () => { throw new Error('Error') } | |
| stream.flush = () => { throw Error('flush should be called') } | |
| const instance = pino(stream) | |
| plan.doesNotThrow(() => instance.fatal(messages[0])) | |
| await plan | |
| }) | |
| test('calling silent method on logger instance', async () => { | |
| const instance = pino({ level: 'silent' }, sink((result, enc) => { | |
| throw Error('no data should be logged') | |
| })) | |
| instance.silent('hello world') | |
| }) | |
| test('calling silent method on child logger', async () => { | |
| const child = pino({ level: 'silent' }, sink((result, enc) => { | |
| throw Error('no data should be logged') | |
| })).child({}) | |
| child.silent('hello world') | |
| }) | |
| test('changing level from info to silent and back to info', async () => { | |
| const expected = { | |
| level: 30, | |
| msg: 'hello world' | |
| } | |
| const stream = sink() | |
| const instance = pino({ level: 'info' }, stream) | |
| instance.level = 'silent' | |
| instance.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| instance.level = 'info' | |
| instance.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('changing level from info to silent and back to info in child logger', async () => { | |
| const expected = { | |
| level: 30, | |
| msg: 'hello world' | |
| } | |
| const stream = sink() | |
| const child = pino({ level: 'info' }, stream).child({}) | |
| child.level = 'silent' | |
| child.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| child.level = 'info' | |
| child.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| describe('changing level respects level comparison set to', () => { | |
| const ascLevels = { | |
| debug: 1, | |
| info: 2, | |
| warn: 3 | |
| } | |
| const descLevels = { | |
| debug: 3, | |
| info: 2, | |
| warn: 1 | |
| } | |
| const expected = { | |
| level: 2, | |
| msg: 'hello world' | |
| } | |
| test('ASC in parent logger', async () => { | |
| const customLevels = ascLevels | |
| const levelComparison = 'ASC' | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('DESC in parent logger', async () => { | |
| const customLevels = descLevels | |
| const levelComparison = 'DESC' | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('custom function in parent logger', async () => { | |
| const customLevels = { | |
| info: 2, | |
| debug: 345, | |
| warn: 789 | |
| } | |
| const levelComparison = (current, expected) => { | |
| if (expected === customLevels.warn) return false | |
| return true | |
| } | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('ASC in child logger', async () => { | |
| const customLevels = ascLevels | |
| const levelComparison = 'ASC' | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream).child({ }) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('DESC in parent logger', async () => { | |
| const customLevels = descLevels | |
| const levelComparison = 'DESC' | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream).child({ }) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| test('custom function in child logger', async () => { | |
| const customLevels = { | |
| info: 2, | |
| debug: 345, | |
| warn: 789 | |
| } | |
| const levelComparison = (current, expected) => { | |
| if (expected === customLevels.warn) return false | |
| return true | |
| } | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream).child({ }) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| }) | |
| test('changing level respects level comparison DESC', async () => { | |
| const customLevels = { | |
| warn: 1, | |
| info: 2, | |
| debug: 3 | |
| } | |
| const levelComparison = 'DESC' | |
| const expected = { | |
| level: 2, | |
| msg: 'hello world' | |
| } | |
| const stream = sink() | |
| const logger = pino({ levelComparison, customLevels, useOnlyCustomLevels: true, level: 'info' }, stream) | |
| logger.level = 'warn' | |
| logger.info('hello world') | |
| let result = stream.read() | |
| assert.equal(result, null) | |
| logger.level = 'debug' | |
| logger.info('hello world') | |
| result = await once(stream, 'data') | |
| check(assert.equal, result, expected.level, expected.msg) | |
| }) | |
| // testing for potential loss of Pino constructor scope from serializers - an edge case with circular refs see: https://github.com/pinojs/pino/issues/833 | |
| test('trying to get levels when `this` is no longer a Pino instance returns an empty string', async () => { | |
| const notPinoInstance = { some: 'object', getLevel: levelsLib.getLevel } | |
| const blankedLevelValue = notPinoInstance.getLevel() | |
| assert.equal(blankedLevelValue, '') | |
| }) | |
| test('accepts capital letter for INFO level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'INFO' | |
| }, stream) | |
| logger.info('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 30) | |
| }) | |
| test('accepts capital letter for FATAL level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'FATAL' | |
| }, stream) | |
| logger.fatal('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 60) | |
| }) | |
| test('accepts capital letter for ERROR level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'ERROR' | |
| }, stream) | |
| logger.error('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 50) | |
| }) | |
| test('accepts capital letter for WARN level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'WARN' | |
| }, stream) | |
| logger.warn('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 40) | |
| }) | |
| test('accepts capital letter for DEBUG level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'DEBUG' | |
| }, stream) | |
| logger.debug('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 20) | |
| }) | |
| test('accepts capital letter for TRACE level', async () => { | |
| const stream = sink() | |
| const logger = pino({ | |
| level: 'TRACE' | |
| }, stream) | |
| logger.trace('test') | |
| const { level } = await once(stream, 'data') | |
| assert.equal(level, 10) | |
| }) | |
Xet Storage Details
- Size:
- 19.8 kB
- Xet hash:
- 8f460f965bfb2796a72bf3d20c4cbca0df2d8c42fe06a4e23e8617fa5909623c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.