pino-pretty
Version:
Prettifier for Pino log lines
162 lines (141 loc) • 4.16 kB
JavaScript
const chalk = require('chalk')
const jmespath = require('jmespath')
const colors = require('./lib/colors')
const { ERROR_LIKE_KEYS, MESSAGE_KEY, TIMESTAMP_KEY } = require('./lib/constants')
const {
isObject,
prettifyErrorLog,
prettifyLevel,
prettifyMessage,
prettifyMetadata,
prettifyObject,
prettifyTime
} = require('./lib/utils')
const bourne = require('@hapi/bourne')
const jsonParser = input => {
try {
return { value: bourne.parse(input, { protoAction: 'remove' }) }
} catch (err) {
return { err }
}
}
const defaultOptions = {
colorize: chalk.supportsColor,
crlf: false,
errorLikeObjectKeys: ERROR_LIKE_KEYS,
errorProps: '',
levelFirst: false,
messageKey: MESSAGE_KEY,
messageFormat: false,
timestampKey: TIMESTAMP_KEY,
translateTime: false,
useMetadata: false,
outputStream: process.stdout,
customPrettifiers: {},
hideObject: false
}
module.exports = function prettyFactory (options) {
const opts = Object.assign({}, defaultOptions, options)
const EOL = opts.crlf ? '\r\n' : '\n'
const IDENT = ' '
const messageKey = opts.messageKey
const levelKey = opts.levelKey
const levelLabel = opts.levelLabel
const messageFormat = opts.messageFormat
const timestampKey = opts.timestampKey
const errorLikeObjectKeys = opts.errorLikeObjectKeys
const errorProps = opts.errorProps.split(',')
const customPrettifiers = opts.customPrettifiers
const ignoreKeys = opts.ignore ? new Set(opts.ignore.split(',')) : undefined
const hideObject = opts.hideObject
const colorizer = colors(opts.colorize)
const search = opts.search
return pretty
function pretty (inputData) {
let log
if (!isObject(inputData)) {
const parsed = jsonParser(inputData)
if (parsed.err || !isObject(parsed.value)) {
// pass through
return inputData + EOL
}
log = parsed.value
} else {
log = inputData
}
if (search && !jmespath.search(log, search)) {
return
}
const prettifiedMessage = prettifyMessage({ log, messageKey, colorizer, messageFormat, levelLabel })
if (ignoreKeys) {
log = Object.keys(log)
.filter(key => !ignoreKeys.has(key))
.reduce((res, key) => {
res[key] = log[key]
return res
}, {})
}
const prettifiedLevel = prettifyLevel({ log, colorizer, levelKey })
const prettifiedMetadata = prettifyMetadata({ log })
const prettifiedTime = prettifyTime({ log, translateFormat: opts.translateTime, timestampKey })
let line = ''
if (opts.levelFirst && prettifiedLevel) {
line = `${prettifiedLevel}`
}
if (prettifiedTime && line === '') {
line = `${prettifiedTime}`
} else if (prettifiedTime) {
line = `${line} ${prettifiedTime}`
}
if (!opts.levelFirst && prettifiedLevel) {
if (line.length > 0) {
line = `${line} ${prettifiedLevel}`
} else {
line = prettifiedLevel
}
}
if (prettifiedMetadata) {
if (line.length > 0) {
line = `${line} ${prettifiedMetadata}:`
} else {
line = prettifiedMetadata
}
}
if (line.endsWith(':') === false && line !== '') {
line += ':'
}
if (prettifiedMessage) {
if (line.length > 0) {
line = `${line} ${prettifiedMessage}`
} else {
line = prettifiedMessage
}
}
if (line.length > 0) {
line += EOL
}
if (log.type === 'Error' && log.stack) {
const prettifiedErrorLog = prettifyErrorLog({
log,
errorLikeKeys: errorLikeObjectKeys,
errorProperties: errorProps,
ident: IDENT,
eol: EOL
})
line += prettifiedErrorLog
} else if (!hideObject) {
const skipKeys = [messageKey, levelKey, timestampKey].filter(key => typeof log[key] === 'string' || typeof log[key] === 'number')
const prettifiedObject = prettifyObject({
input: log,
skipKeys,
customPrettifiers,
errorLikeKeys: errorLikeObjectKeys,
eol: EOL,
ident: IDENT
})
line += prettifiedObject
}
return line
}
}