Skip to content

Instantly share code, notes, and snippets.

@Raynos
Created October 23, 2019 01:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Raynos/102b1dd48eedbe380bdc529643dc3fd1 to your computer and use it in GitHub Desktop.
Save Raynos/102b1dd48eedbe380bdc529643dc3fd1 to your computer and use it in GitHub Desktop.
'use strict'
const pino = require('pino')
const os = require('os')
const { modes } = require('./logger.js')
/**
* This class gives an improved interface for pino
*
* We want info(msg, object) so we swap arguments
*
* This class will also find any top level fields that are an
* error object and will fix the JSON serialization for
* the error object itself.
*
*/
class PinoLogger {
constructor (pino) {
this.pino = pino
}
info (message, meta) {
if (typeof message !== 'string') {
return panic('Logger.info(message), message required')
}
if (meta && typeof meta !== 'object') {
return panic('Logger.info(message, obj), obj must be object')
}
for (const k of Object.keys(meta)) {
if (isError(meta[k])) {
meta[k] = errorToObject(meta[k])
}
}
this.pino.info(meta, message)
}
warn (message, meta) {
if (typeof message !== 'string') {
return panic('Logger.info(message), message required')
}
if (meta && typeof meta !== 'object') {
return panic('Logger.info(message, obj), obj must be object')
}
for (const k of Object.keys(meta)) {
if (isError(meta[k])) {
meta[k] = errorToObject(meta[k])
}
}
this.pino.warn(meta, message)
}
error (message, meta) {
if (typeof message !== 'string') {
return panic('Logger.info(message), message required')
}
if (meta && typeof meta !== 'object') {
return panic('Logger.info(message, obj), obj must be object')
}
for (const k of Object.keys(meta)) {
if (isError(meta[k])) {
meta[k] = errorToObject(meta[k])
}
}
this.pino.error(meta, message)
}
}
module.exports = createJSONLogger
function createJSONLogger (appName, defaults, options = {}) {
if (modes.normal) {
throw new Error('Cannot call getLogger() and createJSONLogger()')
}
modes.json = true
const baseFields = {
pid: process.pid,
hostname: os.hostname(),
...defaults
}
const logger = new PinoLogger(pino({
name: appName,
messageKey: 'message',
useLevelLabels: true,
timestamp: () => {
const d = new Date()
return `,"time":"${d.toISOString()}"`
},
base: baseFields
}, options.destination || pino.destination(1)))
return logger
}
function isError (err) {
if (typeof err !== 'object') {
return false
}
if (err instanceof Error) {
return true
}
while (err) {
if (Object.prototype.toString.call(err) === '[object Error]') {
return true
}
err = Object.getPrototypeOf(err)
}
return false
}
function stackToString (e) {
let stack = e.stack
let causeError
if (typeof e.cause === 'function') {
causeError = e.cause()
stack += '\nCaused by: ' + stackToString(causeError)
}
return stack
}
function errorToObject (err) {
const ret = { ...err }
ret.name = err.name
ret.message = err.message
ret.type = err.type
ret.stack = stackToString(err)
return ret
}
function panic (message) {
const err = new Error(message)
process.nextTick(() => { throw err })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment