Created
October 23, 2019 01:57
-
-
Save Raynos/102b1dd48eedbe380bdc529643dc3fd1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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