'use strict' var format = require('quick-format-unescaped') module.exports = pino var _console = pfGlobalThisOrFallback().console || {} var stdSerializers = { mapHttpRequest: mock, mapHttpResponse: mock, wrapRequestSerializer: passthrough, wrapResponseSerializer: passthrough, wrapErrorSerializer: passthrough, req: mock, res: mock, err: asErrValue } function pino (opts) { opts = opts || {} opts.browser = opts.browser || {} var transmit = opts.browser.transmit if (transmit && typeof transmit.send !== 'function') { throw Error('pino: transmit option must have a send function') } var proto = opts.browser.write || _console if (opts.browser.write) opts.browser.asObject = true var serializers = opts.serializers || {} var serialize = Array.isArray(opts.browser.serialize) ? opts.browser.serialize.filter(function (k) { return k !== '!stdSerializers.err' }) : opts.browser.serialize === true ? Object.keys(serializers) : false var stdErrSerialize = opts.browser.serialize if ( Array.isArray(opts.browser.serialize) && opts.browser.serialize.indexOf('!stdSerializers.err') > -1 ) stdErrSerialize = false var levels = ['error', 'fatal', 'warn', 'info', 'debug', 'trace'] if (typeof proto === 'function') { proto.error = proto.fatal = proto.warn = proto.info = proto.debug = proto.trace = proto } if (opts.enabled === false) opts.level = 'silent' var level = opts.level || 'info' var logger = Object.create(proto) if (!logger.log) logger.log = noop Object.defineProperty(logger, 'levelVal', { get: getLevelVal }) Object.defineProperty(logger, 'level', { get: getLevel, set: setLevel }) var setOpts = { transmit: transmit, serialize: serialize, asObject: opts.browser.asObject, levels: levels } logger.levels = pino.levels logger.level = level logger.setMaxListeners = logger.getMaxListeners = logger.emit = logger.addListener = logger.on = logger.prependListener = logger.once = logger.prependOnceListener = logger.removeListener = logger.removeAllListeners = logger.listeners = logger.listenerCount = logger.eventNames = logger.write = logger.flush = noop logger.serializers = serializers logger._serialize = serialize logger._stdErrSerialize = stdErrSerialize logger.child = child if (transmit) logger._logEvent = createLogEventShape() function getLevelVal () { return this.level === 'silent' ? Infinity : this.levels.values[this.level] } function getLevel () { return this._level } function setLevel (level) { if (level !== 'silent' && !this.levels.values[level]) { throw Error('unknown level ' + level) } this._level = level set(setOpts, logger, 'error', 'log') // <-- must stay first set(setOpts, logger, 'fatal', 'error') set(setOpts, logger, 'warn', 'error') set(setOpts, logger, 'info', 'log') set(setOpts, logger, 'debug', 'log') set(setOpts, logger, 'trace', 'log') } function child (bindings) { if (!bindings) { throw new Error('missing bindings for child Pino') } var bindingsSerializers = bindings.serializers if (serialize && bindingsSerializers) { var childSerializers = Object.assign({}, serializers, bindingsSerializers) var childSerialize = opts.browser.serialize === true ? Object.keys(childSerializers) : serialize delete bindings.serializers applySerializers([bindings], childSerialize, childSerializers, this._stdErrSerialize) } function Child (parent) { this._childLevel = (parent._childLevel | 0) + 1 this.error = bind(parent, bindings, 'error') this.fatal = bind(parent, bindings, 'fatal') this.warn = bind(parent, bindings, 'warn') this.info = bind(parent, bindings, 'info') this.debug = bind(parent, bindings, 'debug') this.trace = bind(parent, bindings, 'trace') if (childSerializers) { this.serializers = childSerializers this._serialize = childSerialize } if (transmit) { this._logEvent = createLogEventShape( [].concat(parent._logEvent.bindings, bindings) ) } } Child.prototype = this return new Child(this) } return logger } pino.LOG_VERSION = 1 pino.levels = { values: { fatal: 60, error: 50, warn: 40, info: 30, debug: 20, trace: 10 }, labels: { 10: 'trace', 20: 'debug', 30: 'info', 40: 'warn', 50: 'error', 60: 'fatal' } } pino.stdSerializers = stdSerializers function set (opts, logger, level, fallback) { var proto = Object.getPrototypeOf(logger) logger[level] = logger.levelVal > logger.levels.values[level] ? noop : (proto[level] ? proto[level] : (_console[level] || _console[fallback] || noop)) wrap(opts, logger, level) } function wrap (opts, logger, level) { if (!opts.transmit && logger[level] === noop) return logger[level] = (function (write) { return function LOG () { var ts = Date.now() var args = new Array(arguments.length) var proto = (Object.getPrototypeOf && Object.getPrototypeOf(this) === _console) ? _console : this for (var i = 0; i < args.length; i++) args[i] = arguments[i] if (opts.serialize && !opts.asObject) { applySerializers(args, this._serialize, this.serializers, this._stdErrSerialize) } if (opts.asObject) write.call(proto, asObject(this, level, args, ts)) else write.apply(proto, args) if (opts.transmit) { var transmitLevel = opts.transmit.level || logger.level var transmitValue = pino.levels.values[transmitLevel] var methodValue = pino.levels.values[level] if (methodValue < transmitValue) return transmit(this, { ts: ts, methodLevel: level, methodValue: methodValue, transmitLevel: transmitLevel, transmitValue: pino.levels.values[opts.transmit.level || logger.level], send: opts.transmit.send, val: logger.levelVal }, args) } } })(logger[level]) } function asObject (logger, level, args, ts) { if (logger._serialize) applySerializers(args, logger._serialize, logger.serializers, logger._stdErrSerialize) var argsCloned = args.slice() var msg = argsCloned[0] var o = { time: ts, level: pino.levels.values[level] } var lvl = (logger._childLevel | 0) + 1 if (lvl < 1) lvl = 1 // deliberate, catching objects, arrays if (msg !== null && typeof msg === 'object') { while (lvl-- && typeof argsCloned[0] === 'object') { Object.assign(o, argsCloned.shift()) } msg = argsCloned.length ? format(argsCloned.shift(), argsCloned) : undefined } else if (typeof msg === 'string') msg = format(argsCloned.shift(), argsCloned) if (msg !== undefined) o.msg = msg return o } function applySerializers (args, serialize, serializers, stdErrSerialize) { for (var i in args) { if (stdErrSerialize && args[i] instanceof Error) { args[i] = pino.stdSerializers.err(args[i]) } else if (typeof args[i] === 'object' && !Array.isArray(args[i])) { for (var k in args[i]) { if (serialize && serialize.indexOf(k) > -1 && k in serializers) { args[i][k] = serializers[k](args[i][k]) } } } } } function bind (parent, bindings, level) { return function () { var args = new Array(1 + arguments.length) args[0] = bindings for (var i = 1; i < args.length; i++) { args[i] = arguments[i - 1] } return parent[level].apply(this, args) } } function transmit (logger, opts, args) { var send = opts.send var ts = opts.ts var methodLevel = opts.methodLevel var methodValue = opts.methodValue var val = opts.val var bindings = logger._logEvent.bindings applySerializers( args, logger._serialize || Object.keys(logger.serializers), logger.serializers, logger._stdErrSerialize === undefined ? true : logger._stdErrSerialize ) logger._logEvent.ts = ts logger._logEvent.messages = args.filter(function (arg) { // bindings can only be objects, so reference equality check via indexOf is fine return bindings.indexOf(arg) === -1 }) logger._logEvent.level.label = methodLevel logger._logEvent.level.value = methodValue send(methodLevel, logger._logEvent, val) logger._logEvent = createLogEventShape(bindings) } function createLogEventShape (bindings) { return { ts: 0, messages: [], bindings: bindings || [], level: { label: '', value: 0 } } } function asErrValue (err) { var obj = { type: err.constructor.name, msg: err.message, stack: err.stack } for (var key in err) { if (obj[key] === undefined) { obj[key] = err[key] } } return obj } function mock () { return {} } function passthrough (a) { return a } function noop () {} /* eslint-disable */ /* istanbul ignore next */ function pfGlobalThisOrFallback () { function defd (o) { return typeof o !== 'undefined' && o } try { if (typeof globalThis !== 'undefined') return globalThis Object.defineProperty(Object.prototype, 'globalThis', { get: function () { delete Object.prototype.globalThis return (this.globalThis = this) }, configurable: true }) return globalThis } catch (e) { return defd(self) || defd(window) || defd(this) || {} } } /* eslint-enable */