brf/server/lib/pino_transport_console.ts
2025-11-24 17:09:09 +01:00

72 lines
1.9 KiB
TypeScript

import util from 'node:util'
import chalk from 'chalk'
import _ from 'lodash'
import highlightStack from '@bmp/highlight-stack'
const LEVELS = {
default: 'USERLVL',
60: 'FATAL',
50: 'ERROR',
40: 'WARN',
30: 'INFO',
20: 'DEBUG',
10: 'TRACE',
}
const COLORS = {
60: chalk.bgRed,
50: chalk.red,
40: chalk.yellow,
30: chalk.green,
20: chalk.blue,
10: chalk.grey,
}
const requests = new Map()
function colorStatusCode(statusCode) {
if (statusCode < 300) {
return chalk.bold.green(statusCode)
} else if (statusCode < 400) {
return chalk.bold.blue(statusCode)
} else if (statusCode < 500) {
return chalk.bold.yellow(statusCode)
} else {
return chalk.bold.red(statusCode)
}
}
export default {
write(line) {
const obj = JSON.parse(line)
if (obj.msg === 'incoming request') {
requests.set(obj.reqId, obj.req)
} else if (obj.msg === 'request completed') {
const req = requests.get(obj.reqId)
requests.delete(obj.reqId)
process.stdout.write(
`${chalk.bold(req.method)} ${req.url} ${colorStatusCode(obj.res.statusCode)} ${obj.responseTime.toFixed(
3,
)} ms\n`,
)
} else if (obj.level === 50) {
// TODO figure out if there is a way to get the error instances here... console.log(Error) and util.inspect(Error)
// looks better than the serialized errors
if (obj.err.status < 500) return
process.stdout.write(
`${COLORS[obj.level](LEVELS[obj.level] || LEVELS.default)} ${highlightStack(obj.err.stack)}\n`,
)
const details = _.omit(obj.err, ['type', 'message', 'stack'])
if (!_.isEmpty(details)) {
process.stdout.write(`${chalk.red('Details')} ${util.inspect(details, false, 4, true)}\n`)
}
} else {
process.stdout.write(`${COLORS[obj.level](LEVELS[obj.level] || LEVELS.default)} ${obj.msg}\n`)
}
},
}