UNPKG

pino-pretty

Version:
190 lines (179 loc) 6.87 kB
'use strict' const { isColorSupported } = require('colorette') const pump = require('pump') const { Transform } = require('stream') const abstractTransport = require('pino-abstract-transport') const colors = require('./lib/colors') const { ERROR_LIKE_KEYS, LEVEL_KEY, LEVEL_LABEL, MESSAGE_KEY, TIMESTAMP_KEY } = require('./lib/constants') const { buildSafeSonicBoom, parseFactoryOptions } = require('./lib/utils') const pretty = require('./lib/pretty') /** * @typedef {object} PinoPrettyOptions * @property {boolean} [colorize] Indicates if colors should be used when * prettifying. The default will be determined by the terminal capabilities at * run time. * @property {boolean} [colorizeObjects=true] Apply coloring to rendered objects * when coloring is enabled. * @property {boolean} [crlf=false] End lines with `\r\n` instead of `\n`. * @property {string|null} [customColors=null] A comma separated list of colors * to use for specific level labels, e.g. `err:red,info:blue`. * @property {string|null} [customLevels=null] A comma separated list of user * defined level names and numbers, e.g. `err:99,info:1`. * @property {CustomPrettifiers} [customPrettifiers={}] A set of prettifier * functions to apply to keys defined in this object. * @property {K_ERROR_LIKE_KEYS} [errorLikeObjectKeys] A list of string property * names to consider as error objects. * @property {string} [errorProps=''] A comma separated list of properties on * error objects to include in the output. * @property {boolean} [hideObject=false] When `true`, data objects will be * omitted from the output (except for error objects). * @property {string} [ignore='hostname'] A comma separated list of log keys * to omit when outputting the prettified log information. * @property {undefined|string} [include=undefined] A comma separated list of * log keys to include in the prettified log information. Only the keys in this * list will be included in the output. * @property {boolean} [levelFirst=false] When true, the log level will be the * first field in the prettified output. * @property {string} [levelKey='level'] The key name in the log data that * contains the level value for the log. * @property {string} [levelLabel='levelLabel'] Token name to use in * `messageFormat` to represent the name of the logged level. * @property {null|MessageFormatString|MessageFormatFunction} [messageFormat=null] * When a string, defines how the prettified line should be formatted according * to defined tokens. When a function, a synchronous function that returns a * formatted string. * @property {string} [messageKey='msg'] Defines the key in incoming logs that * contains the message of the log, if present. * @property {undefined|string|number} [minimumLevel=undefined] The minimum * level for logs that should be processed. Any logs below this level will * be omitted. * @property {object} [outputStream=process.stdout] The stream to write * prettified log lines to. * @property {boolean} [singleLine=false] When `true` any objects, except error * objects, in the log data will be printed as a single line instead as multiple * lines. * @property {string} [timestampKey='time'] Defines the key in incoming logs * that contains the timestamp of the log, if present. * @property {boolean|string} [translateTime=true] When true, will translate a * JavaScript date integer into a human-readable string. If set to a string, * it must be a format string. * @property {boolean} [useOnlyCustomProps=true] When true, only custom levels * and colors will be used if they have been provided. */ /** * The default options that will be used when prettifying log lines. * * @type {PinoPrettyOptions} */ const defaultOptions = { colorize: isColorSupported, colorizeObjects: true, crlf: false, customColors: null, customLevels: null, customPrettifiers: {}, errorLikeObjectKeys: ERROR_LIKE_KEYS, errorProps: '', hideObject: false, ignore: 'hostname', include: undefined, levelFirst: false, levelKey: LEVEL_KEY, levelLabel: LEVEL_LABEL, messageFormat: null, messageKey: MESSAGE_KEY, minimumLevel: undefined, outputStream: process.stdout, singleLine: false, timestampKey: TIMESTAMP_KEY, translateTime: true, useOnlyCustomProps: true } /** * Processes the supplied options and returns a function that accepts log data * and produces a prettified log string. * * @param {PinoPrettyOptions} options Configuration for the prettifier. * @returns {LogPrettifierFunc} */ function prettyFactory (options) { const context = parseFactoryOptions(Object.assign({}, defaultOptions, options)) return pretty.bind({ ...context, context }) } /** * @typedef {PinoPrettyOptions} BuildStreamOpts * @property {object|number|string} [destination] A destination stream, file * descriptor, or target path to a file. * @property {boolean} [append] * @property {boolean} [mkdir] * @property {boolean} [sync=false] */ /** * Constructs a {@link LogPrettifierFunc} and a stream to which the produced * prettified log data will be written. * * @param {BuildStreamOpts} opts * @returns {Transform | (Transform & OnUnknown)} */ function build (opts = {}) { let pretty = prettyFactory(opts) let destination return abstractTransport(function (source) { source.on('message', function pinoConfigListener (message) { if (!message || message.code !== 'PINO_CONFIG') return Object.assign(opts, { messageKey: message.config.messageKey, errorLikeObjectKeys: Array.from(new Set([...(opts.errorLikeObjectKeys || ERROR_LIKE_KEYS), message.config.errorKey])), customLevels: message.config.levels.values }) pretty = prettyFactory(opts) source.off('message', pinoConfigListener) }) const stream = new Transform({ objectMode: true, autoDestroy: true, transform (chunk, enc, cb) { const line = pretty(chunk) cb(null, line) } }) if (typeof opts.destination === 'object' && typeof opts.destination.write === 'function') { destination = opts.destination } else { destination = buildSafeSonicBoom({ dest: opts.destination || 1, append: opts.append, mkdir: opts.mkdir, sync: opts.sync // by default sonic will be async }) } source.on('unknown', function (line) { destination.write(line + '\n') }) pump(source, stream, destination) return stream }, { parse: 'lines', close (err, cb) { destination.on('close', () => { cb(err) }) } }) } module.exports = build module.exports.build = build module.exports.PinoPretty = build module.exports.prettyFactory = prettyFactory module.exports.colorizerFactory = colors module.exports.isColorSupported = isColorSupported module.exports.default = build