update
This commit is contained in:
parent
d9becc67b6
commit
9308795b8b
964 changed files with 104265 additions and 16 deletions
183
node_modules/pino/lib/levels.js
generated
vendored
Normal file
183
node_modules/pino/lib/levels.js
generated
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
'use strict'
|
||||
const flatstr = require('flatstr')
|
||||
const {
|
||||
lsCacheSym,
|
||||
levelValSym,
|
||||
useLevelLabelsSym,
|
||||
levelKeySym,
|
||||
useOnlyCustomLevelsSym,
|
||||
streamSym
|
||||
} = require('./symbols')
|
||||
const { noop, genLog } = require('./tools')
|
||||
|
||||
const levels = {
|
||||
trace: 10,
|
||||
debug: 20,
|
||||
info: 30,
|
||||
warn: 40,
|
||||
error: 50,
|
||||
fatal: 60
|
||||
}
|
||||
const logFatal = genLog(levels.fatal)
|
||||
const levelMethods = {
|
||||
fatal (...args) {
|
||||
const stream = this[streamSym]
|
||||
logFatal.call(this, ...args)
|
||||
if (typeof stream.flushSync === 'function') {
|
||||
try {
|
||||
stream.flushSync()
|
||||
} catch (e) {
|
||||
// https://github.com/pinojs/pino/pull/740#discussion_r346788313
|
||||
}
|
||||
}
|
||||
},
|
||||
error: genLog(levels.error),
|
||||
warn: genLog(levels.warn),
|
||||
info: genLog(levels.info),
|
||||
debug: genLog(levels.debug),
|
||||
trace: genLog(levels.trace)
|
||||
}
|
||||
|
||||
const nums = Object.keys(levels).reduce((o, k) => {
|
||||
o[levels[k]] = k
|
||||
return o
|
||||
}, {})
|
||||
|
||||
const initialLsCache = Object.keys(nums).reduce((o, k) => {
|
||||
o[k] = flatstr('{"level":' + Number(k))
|
||||
return o
|
||||
}, {})
|
||||
|
||||
function genLsCache (instance) {
|
||||
const levelName = instance[levelKeySym]
|
||||
instance[lsCacheSym] = Object.keys(instance.levels.labels).reduce((o, k) => {
|
||||
o[k] = instance[useLevelLabelsSym]
|
||||
? `{"${levelName}":"${instance.levels.labels[k]}"`
|
||||
: flatstr(`{"${levelName}":` + Number(k))
|
||||
return o
|
||||
}, Object.assign({}, instance[lsCacheSym]))
|
||||
return instance
|
||||
}
|
||||
|
||||
function isStandardLevel (level, useOnlyCustomLevels) {
|
||||
if (useOnlyCustomLevels) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case 'fatal':
|
||||
case 'error':
|
||||
case 'warn':
|
||||
case 'info':
|
||||
case 'debug':
|
||||
case 'trace':
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function setLevel (level) {
|
||||
const { labels, values } = this.levels
|
||||
if (typeof level === 'number') {
|
||||
if (labels[level] === undefined) throw Error('unknown level value' + level)
|
||||
level = labels[level]
|
||||
}
|
||||
if (values[level] === undefined) throw Error('unknown level ' + level)
|
||||
const preLevelVal = this[levelValSym]
|
||||
const levelVal = this[levelValSym] = values[level]
|
||||
const useOnlyCustomLevelsVal = this[useOnlyCustomLevelsSym]
|
||||
|
||||
for (var key in values) {
|
||||
if (levelVal > values[key]) {
|
||||
this[key] = noop
|
||||
continue
|
||||
}
|
||||
this[key] = isStandardLevel(key, useOnlyCustomLevelsVal) ? levelMethods[key] : genLog(values[key])
|
||||
}
|
||||
|
||||
this.emit(
|
||||
'level-change',
|
||||
level,
|
||||
levelVal,
|
||||
labels[preLevelVal],
|
||||
preLevelVal
|
||||
)
|
||||
}
|
||||
|
||||
function getLevel (level) {
|
||||
const { levels, levelVal } = this
|
||||
return levels.labels[levelVal]
|
||||
}
|
||||
|
||||
function isLevelEnabled (logLevel) {
|
||||
const { values } = this.levels
|
||||
const logLevelVal = values[logLevel]
|
||||
return logLevelVal !== undefined && (logLevelVal >= this[levelValSym])
|
||||
}
|
||||
|
||||
function mappings (customLevels = null, useOnlyCustomLevels = false) {
|
||||
const customNums = customLevels ? Object.keys(customLevels).reduce((o, k) => {
|
||||
o[customLevels[k]] = k
|
||||
return o
|
||||
}, {}) : null
|
||||
|
||||
const labels = Object.assign(
|
||||
Object.create(Object.prototype, { Infinity: { value: 'silent' } }),
|
||||
useOnlyCustomLevels ? null : nums,
|
||||
customNums
|
||||
)
|
||||
const values = Object.assign(
|
||||
Object.create(Object.prototype, { silent: { value: Infinity } }),
|
||||
useOnlyCustomLevels ? null : levels,
|
||||
customLevels
|
||||
)
|
||||
return { labels, values }
|
||||
}
|
||||
|
||||
function assertDefaultLevelFound (defaultLevel, customLevels, useOnlyCustomLevels) {
|
||||
if (typeof defaultLevel === 'number') {
|
||||
const values = [].concat(
|
||||
Object.keys(customLevels || {}).map(key => customLevels[key]),
|
||||
useOnlyCustomLevels ? [] : Object.keys(nums).map(level => +level),
|
||||
Infinity
|
||||
)
|
||||
if (!values.includes(defaultLevel)) {
|
||||
throw Error(`default level:${defaultLevel} must be included in custom levels`)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const labels = Object.assign(
|
||||
Object.create(Object.prototype, { silent: { value: Infinity } }),
|
||||
useOnlyCustomLevels ? null : levels,
|
||||
customLevels
|
||||
)
|
||||
if (!(defaultLevel in labels)) {
|
||||
throw Error(`default level:${defaultLevel} must be included in custom levels`)
|
||||
}
|
||||
}
|
||||
|
||||
function assertNoLevelCollisions (levels, customLevels) {
|
||||
const { labels, values } = levels
|
||||
for (const k in customLevels) {
|
||||
if (k in values) {
|
||||
throw Error('levels cannot be overridden')
|
||||
}
|
||||
if (customLevels[k] in labels) {
|
||||
throw Error('pre-existing level values cannot be used for new levels')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initialLsCache,
|
||||
genLsCache,
|
||||
levelMethods,
|
||||
getLevel,
|
||||
setLevel,
|
||||
isLevelEnabled,
|
||||
mappings,
|
||||
assertNoLevelCollisions,
|
||||
assertDefaultLevelFound
|
||||
}
|
7
node_modules/pino/lib/meta.js
generated
vendored
Normal file
7
node_modules/pino/lib/meta.js
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
const { version } = require('../package.json')
|
||||
|
||||
const LOG_VERSION = 1
|
||||
|
||||
module.exports = { version, LOG_VERSION }
|
167
node_modules/pino/lib/proto.js
generated
vendored
Normal file
167
node_modules/pino/lib/proto.js
generated
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
'use strict'
|
||||
|
||||
/* eslint no-prototype-builtins: 0 */
|
||||
|
||||
const { EventEmitter } = require('events')
|
||||
const SonicBoom = require('sonic-boom')
|
||||
const flatstr = require('flatstr')
|
||||
const {
|
||||
lsCacheSym,
|
||||
levelValSym,
|
||||
setLevelSym,
|
||||
getLevelSym,
|
||||
chindingsSym,
|
||||
mixinSym,
|
||||
asJsonSym,
|
||||
messageKeySym,
|
||||
writeSym,
|
||||
timeSym,
|
||||
timeSliceIndexSym,
|
||||
streamSym,
|
||||
serializersSym,
|
||||
useOnlyCustomLevelsSym,
|
||||
needsMetadataGsym
|
||||
} = require('./symbols')
|
||||
const {
|
||||
getLevel,
|
||||
setLevel,
|
||||
isLevelEnabled,
|
||||
mappings,
|
||||
initialLsCache,
|
||||
genLsCache,
|
||||
assertNoLevelCollisions
|
||||
} = require('./levels')
|
||||
const {
|
||||
asChindings,
|
||||
asJson
|
||||
} = require('./tools')
|
||||
const {
|
||||
version,
|
||||
LOG_VERSION
|
||||
} = require('./meta')
|
||||
|
||||
// note: use of class is satirical
|
||||
// https://github.com/pinojs/pino/pull/433#pullrequestreview-127703127
|
||||
const constructor = class Pino {}
|
||||
const prototype = {
|
||||
constructor,
|
||||
child,
|
||||
bindings,
|
||||
setBindings,
|
||||
flush,
|
||||
isLevelEnabled,
|
||||
version,
|
||||
get level () { return this[getLevelSym]() },
|
||||
set level (lvl) { return this[setLevelSym](lvl) },
|
||||
get levelVal () { return this[levelValSym] },
|
||||
set levelVal (n) { throw Error('levelVal is read-only') },
|
||||
[lsCacheSym]: initialLsCache,
|
||||
[writeSym]: write,
|
||||
[asJsonSym]: asJson,
|
||||
[getLevelSym]: getLevel,
|
||||
[setLevelSym]: setLevel,
|
||||
LOG_VERSION
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(prototype, EventEmitter.prototype)
|
||||
|
||||
module.exports = prototype
|
||||
|
||||
function child (bindings) {
|
||||
const { level } = this
|
||||
const serializers = this[serializersSym]
|
||||
const chindings = asChindings(this, bindings)
|
||||
const instance = Object.create(this)
|
||||
if (bindings.hasOwnProperty('serializers') === true) {
|
||||
instance[serializersSym] = Object.create(null)
|
||||
|
||||
for (var k in serializers) {
|
||||
instance[serializersSym][k] = serializers[k]
|
||||
}
|
||||
const parentSymbols = Object.getOwnPropertySymbols(serializers)
|
||||
for (var i = 0; i < parentSymbols.length; i++) {
|
||||
const ks = parentSymbols[i]
|
||||
instance[serializersSym][ks] = serializers[ks]
|
||||
}
|
||||
|
||||
for (var bk in bindings.serializers) {
|
||||
instance[serializersSym][bk] = bindings.serializers[bk]
|
||||
}
|
||||
const bindingsSymbols = Object.getOwnPropertySymbols(bindings.serializers)
|
||||
for (var bi = 0; bi < bindingsSymbols.length; bi++) {
|
||||
const bks = bindingsSymbols[bi]
|
||||
instance[serializersSym][bks] = bindings.serializers[bks]
|
||||
}
|
||||
} else instance[serializersSym] = serializers
|
||||
if (bindings.hasOwnProperty('customLevels') === true) {
|
||||
assertNoLevelCollisions(this.levels, bindings.customLevels)
|
||||
instance.levels = mappings(bindings.customLevels, instance[useOnlyCustomLevelsSym])
|
||||
genLsCache(instance)
|
||||
}
|
||||
instance[chindingsSym] = chindings
|
||||
const childLevel = bindings.level || level
|
||||
instance[setLevelSym](childLevel)
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
function bindings () {
|
||||
const chindings = this[chindingsSym]
|
||||
var chindingsJson = `{${chindings.substr(1)}}` // at least contains ,"pid":7068,"hostname":"myMac"
|
||||
var bindingsFromJson = JSON.parse(chindingsJson)
|
||||
delete bindingsFromJson.pid
|
||||
delete bindingsFromJson.hostname
|
||||
return bindingsFromJson
|
||||
}
|
||||
|
||||
function setBindings (newBindings) {
|
||||
const chindings = asChindings(this, newBindings)
|
||||
this[chindingsSym] = chindings
|
||||
}
|
||||
|
||||
function write (_obj, msg, num) {
|
||||
const t = this[timeSym]()
|
||||
const messageKey = this[messageKeySym]
|
||||
const mixin = this[mixinSym]
|
||||
const objError = _obj instanceof Error
|
||||
var obj
|
||||
|
||||
if (_obj === undefined || _obj === null) {
|
||||
obj = mixin ? mixin() : {}
|
||||
obj[messageKey] = msg
|
||||
} else {
|
||||
obj = Object.assign(mixin ? mixin() : {}, _obj)
|
||||
if (msg) {
|
||||
obj[messageKey] = msg
|
||||
} else if (objError) {
|
||||
obj[messageKey] = _obj.message
|
||||
}
|
||||
|
||||
if (objError) {
|
||||
obj.stack = _obj.stack
|
||||
if (!obj.type) {
|
||||
obj.type = 'Error'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const s = this[asJsonSym](obj, num, t)
|
||||
|
||||
const stream = this[streamSym]
|
||||
if (stream[needsMetadataGsym] === true) {
|
||||
stream.lastLevel = num
|
||||
// TODO remove in the next major release,
|
||||
// it is not needed anymore
|
||||
stream.lastMsg = msg
|
||||
stream.lastObj = obj
|
||||
stream.lastTime = t.slice(this[timeSliceIndexSym])
|
||||
stream.lastLogger = this // for child loggers
|
||||
}
|
||||
if (stream instanceof SonicBoom) stream.write(s)
|
||||
else stream.write(flatstr(s))
|
||||
}
|
||||
|
||||
function flush () {
|
||||
const stream = this[streamSym]
|
||||
if ('flush' in stream) stream.flush()
|
||||
}
|
104
node_modules/pino/lib/redaction.js
generated
vendored
Normal file
104
node_modules/pino/lib/redaction.js
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
'use strict'
|
||||
|
||||
const fastRedact = require('fast-redact')
|
||||
const { redactFmtSym, wildcardFirstSym } = require('./symbols')
|
||||
const { rx, validator } = fastRedact
|
||||
|
||||
const validate = validator({
|
||||
ERR_PATHS_MUST_BE_STRINGS: () => 'pino – redacted paths must be strings',
|
||||
ERR_INVALID_PATH: (s) => `pino – redact paths array contains an invalid path (${s})`
|
||||
})
|
||||
|
||||
const CENSOR = '[Redacted]'
|
||||
const strict = false // TODO should this be configurable?
|
||||
|
||||
function redaction (opts, serialize) {
|
||||
const { paths, censor } = handle(opts)
|
||||
|
||||
const shape = paths.reduce((o, str) => {
|
||||
rx.lastIndex = 0
|
||||
const first = rx.exec(str)
|
||||
const next = rx.exec(str)
|
||||
|
||||
// ns is the top-level path segment, brackets + quoting removed.
|
||||
let ns = first[1] !== undefined
|
||||
? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, '$1')
|
||||
: first[0]
|
||||
|
||||
if (ns === '*') {
|
||||
ns = wildcardFirstSym
|
||||
}
|
||||
|
||||
// top level key:
|
||||
if (next === null) {
|
||||
o[ns] = null
|
||||
return o
|
||||
}
|
||||
|
||||
// path with at least two segments:
|
||||
// if ns is already redacted at the top level, ignore lower level redactions
|
||||
if (o[ns] === null) {
|
||||
return o
|
||||
}
|
||||
|
||||
const { index } = next
|
||||
const nextPath = `${str.substr(index, str.length - 1)}`
|
||||
|
||||
o[ns] = o[ns] || []
|
||||
|
||||
// shape is a mix of paths beginning with literal values and wildcard
|
||||
// paths [ "a.b.c", "*.b.z" ] should reduce to a shape of
|
||||
// { "a": [ "b.c", "b.z" ], *: [ "b.z" ] }
|
||||
// note: "b.z" is in both "a" and * arrays because "a" matches the wildcard.
|
||||
// (* entry has wildcardFirstSym as key)
|
||||
if (ns !== wildcardFirstSym && o[ns].length === 0) {
|
||||
// first time ns's get all '*' redactions so far
|
||||
o[ns].push(...(o[wildcardFirstSym] || []))
|
||||
}
|
||||
|
||||
if (ns === wildcardFirstSym) {
|
||||
// new * path gets added to all previously registered literal ns's.
|
||||
Object.keys(o).forEach(function (k) {
|
||||
if (o[k]) {
|
||||
o[k].push(nextPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
o[ns].push(nextPath)
|
||||
return o
|
||||
}, {})
|
||||
|
||||
// the redactor assigned to the format symbol key
|
||||
// provides top level redaction for instances where
|
||||
// an object is interpolated into the msg string
|
||||
const result = {
|
||||
[redactFmtSym]: fastRedact({ paths, censor, serialize, strict })
|
||||
}
|
||||
|
||||
const topCensor = (...args) =>
|
||||
typeof censor === 'function' ? serialize(censor(...args)) : serialize(censor)
|
||||
|
||||
return [...Object.keys(shape), ...Object.getOwnPropertySymbols(shape)].reduce((o, k) => {
|
||||
// top level key:
|
||||
if (shape[k] === null) o[k] = topCensor
|
||||
else o[k] = fastRedact({ paths: shape[k], censor, serialize, strict })
|
||||
return o
|
||||
}, result)
|
||||
}
|
||||
|
||||
function handle (opts) {
|
||||
if (Array.isArray(opts)) {
|
||||
opts = { paths: opts, censor: CENSOR }
|
||||
validate(opts)
|
||||
return opts
|
||||
}
|
||||
var { paths, censor = CENSOR, remove } = opts
|
||||
if (Array.isArray(paths) === false) { throw Error('pino – redact must contain an array of strings') }
|
||||
if (remove === true) censor = undefined
|
||||
validate({ paths, censor })
|
||||
|
||||
return { paths, censor }
|
||||
}
|
||||
|
||||
module.exports = redaction
|
64
node_modules/pino/lib/symbols.js
generated
vendored
Normal file
64
node_modules/pino/lib/symbols.js
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
'use strict'
|
||||
|
||||
const setLevelSym = Symbol('pino.setLevel')
|
||||
const getLevelSym = Symbol('pino.getLevel')
|
||||
const levelValSym = Symbol('pino.levelVal')
|
||||
const useLevelLabelsSym = Symbol('pino.useLevelLabels')
|
||||
const levelKeySym = Symbol('pino.levelKey')
|
||||
const useOnlyCustomLevelsSym = Symbol('pino.useOnlyCustomLevels')
|
||||
const mixinSym = Symbol('pino.mixin')
|
||||
|
||||
const lsCacheSym = Symbol('pino.lsCache')
|
||||
const chindingsSym = Symbol('pino.chindings')
|
||||
const parsedChindingsSym = Symbol('pino.parsedChindings')
|
||||
|
||||
const asJsonSym = Symbol('pino.asJson')
|
||||
const writeSym = Symbol('pino.write')
|
||||
const redactFmtSym = Symbol('pino.redactFmt')
|
||||
|
||||
const timeSym = Symbol('pino.time')
|
||||
const timeSliceIndexSym = Symbol('pino.timeSliceIndex')
|
||||
const streamSym = Symbol('pino.stream')
|
||||
const stringifySym = Symbol('pino.stringify')
|
||||
const stringifiersSym = Symbol('pino.stringifiers')
|
||||
const endSym = Symbol('pino.end')
|
||||
const formatOptsSym = Symbol('pino.formatOpts')
|
||||
const messageKeySym = Symbol('pino.messageKey')
|
||||
const nestedKeySym = Symbol('pino.nestedKey')
|
||||
|
||||
const wildcardFirstSym = Symbol('pino.wildcardFirst')
|
||||
|
||||
// public symbols, no need to use the same pino
|
||||
// version for these
|
||||
const serializersSym = Symbol.for('pino.serializers')
|
||||
const wildcardGsym = Symbol.for('pino.*')
|
||||
const needsMetadataGsym = Symbol.for('pino.metadata')
|
||||
|
||||
module.exports = {
|
||||
setLevelSym,
|
||||
getLevelSym,
|
||||
levelValSym,
|
||||
useLevelLabelsSym,
|
||||
mixinSym,
|
||||
lsCacheSym,
|
||||
chindingsSym,
|
||||
parsedChindingsSym,
|
||||
asJsonSym,
|
||||
writeSym,
|
||||
serializersSym,
|
||||
redactFmtSym,
|
||||
timeSym,
|
||||
timeSliceIndexSym,
|
||||
streamSym,
|
||||
stringifySym,
|
||||
stringifiersSym,
|
||||
endSym,
|
||||
formatOptsSym,
|
||||
messageKeySym,
|
||||
nestedKeySym,
|
||||
wildcardFirstSym,
|
||||
levelKeySym,
|
||||
wildcardGsym,
|
||||
needsMetadataGsym,
|
||||
useOnlyCustomLevelsSym
|
||||
}
|
11
node_modules/pino/lib/time.js
generated
vendored
Normal file
11
node_modules/pino/lib/time.js
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
'use strict'
|
||||
|
||||
const nullTime = () => ''
|
||||
|
||||
const epochTime = () => `,"time":${Date.now()}`
|
||||
|
||||
const unixTime = () => `,"time":${Math.round(Date.now() / 1000.0)}`
|
||||
|
||||
const isoTime = () => `,"time":"${new Date(Date.now()).toISOString()}"` // using Date.now() for testability
|
||||
|
||||
module.exports = { nullTime, epochTime, unixTime, isoTime }
|
386
node_modules/pino/lib/tools.js
generated
vendored
Normal file
386
node_modules/pino/lib/tools.js
generated
vendored
Normal file
|
@ -0,0 +1,386 @@
|
|||
'use strict'
|
||||
|
||||
/* eslint no-prototype-builtins: 0 */
|
||||
|
||||
const format = require('quick-format-unescaped')
|
||||
const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers')
|
||||
const SonicBoom = require('sonic-boom')
|
||||
const stringifySafe = require('fast-safe-stringify')
|
||||
const {
|
||||
lsCacheSym,
|
||||
chindingsSym,
|
||||
parsedChindingsSym,
|
||||
writeSym,
|
||||
serializersSym,
|
||||
formatOptsSym,
|
||||
endSym,
|
||||
stringifiersSym,
|
||||
stringifySym,
|
||||
wildcardFirstSym,
|
||||
needsMetadataGsym,
|
||||
wildcardGsym,
|
||||
redactFmtSym,
|
||||
streamSym,
|
||||
nestedKeySym
|
||||
} = require('./symbols')
|
||||
|
||||
function noop () {}
|
||||
|
||||
function genLog (z) {
|
||||
return function LOG (o, ...n) {
|
||||
if (typeof o === 'object' && o !== null) {
|
||||
if (o.method && o.headers && o.socket) {
|
||||
o = mapHttpRequest(o)
|
||||
} else if (typeof o.setHeader === 'function') {
|
||||
o = mapHttpResponse(o)
|
||||
}
|
||||
if (this[nestedKeySym]) o = { [this[nestedKeySym]]: o }
|
||||
this[writeSym](o, format(null, n, this[formatOptsSym]), z)
|
||||
} else this[writeSym](null, format(o, n, this[formatOptsSym]), z)
|
||||
}
|
||||
}
|
||||
|
||||
// magically escape strings for json
|
||||
// relying on their charCodeAt
|
||||
// everything below 32 needs JSON.stringify()
|
||||
// 34 and 92 happens all the time, so we
|
||||
// have a fast case for them
|
||||
function asString (str) {
|
||||
var result = ''
|
||||
var last = 0
|
||||
var found = false
|
||||
var point = 255
|
||||
const l = str.length
|
||||
if (l > 100) {
|
||||
return JSON.stringify(str)
|
||||
}
|
||||
for (var i = 0; i < l && point >= 32; i++) {
|
||||
point = str.charCodeAt(i)
|
||||
if (point === 34 || point === 92) {
|
||||
result += str.slice(last, i) + '\\'
|
||||
last = i
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
result = str
|
||||
} else {
|
||||
result += str.slice(last)
|
||||
}
|
||||
return point < 32 ? JSON.stringify(str) : '"' + result + '"'
|
||||
}
|
||||
|
||||
function asJson (obj, num, time) {
|
||||
const stringify = this[stringifySym]
|
||||
const stringifiers = this[stringifiersSym]
|
||||
const end = this[endSym]
|
||||
const chindings = this[chindingsSym]
|
||||
const serializers = this[serializersSym]
|
||||
var data = this[lsCacheSym][num] + time
|
||||
|
||||
// we need the child bindings added to the output first so instance logged
|
||||
// objects can take precedence when JSON.parse-ing the resulting log line
|
||||
data = data + chindings
|
||||
|
||||
var value
|
||||
var notHasOwnProperty = obj.hasOwnProperty === undefined
|
||||
if (serializers[wildcardGsym]) {
|
||||
obj = serializers[wildcardGsym](obj)
|
||||
}
|
||||
const wildcardStringifier = stringifiers[wildcardFirstSym]
|
||||
for (var key in obj) {
|
||||
value = obj[key]
|
||||
if ((notHasOwnProperty || obj.hasOwnProperty(key)) && value !== undefined) {
|
||||
value = serializers[key] ? serializers[key](value) : value
|
||||
|
||||
const stringifier = stringifiers[key] || wildcardStringifier
|
||||
|
||||
switch (typeof value) {
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
continue
|
||||
case 'number':
|
||||
/* eslint no-fallthrough: "off" */
|
||||
if (Number.isFinite(value) === false) {
|
||||
value = null
|
||||
}
|
||||
// this case explicity falls through to the next one
|
||||
case 'boolean':
|
||||
if (stringifier) value = stringifier(value)
|
||||
break
|
||||
case 'string':
|
||||
value = (stringifier || asString)(value)
|
||||
break
|
||||
default:
|
||||
value = (stringifier || stringify)(value)
|
||||
}
|
||||
if (value === undefined) continue
|
||||
data += ',"' + key + '":' + value
|
||||
}
|
||||
}
|
||||
|
||||
return data + end
|
||||
}
|
||||
|
||||
function asChindings (instance, bindings) {
|
||||
if (!bindings) {
|
||||
throw Error('missing bindings for child Pino')
|
||||
}
|
||||
var key
|
||||
var value
|
||||
var data = instance[chindingsSym]
|
||||
const stringify = instance[stringifySym]
|
||||
const stringifiers = instance[stringifiersSym]
|
||||
const serializers = instance[serializersSym]
|
||||
if (serializers[wildcardGsym]) {
|
||||
bindings = serializers[wildcardGsym](bindings)
|
||||
}
|
||||
for (key in bindings) {
|
||||
value = bindings[key]
|
||||
const valid = key !== 'level' &&
|
||||
key !== 'serializers' &&
|
||||
key !== 'customLevels' &&
|
||||
bindings.hasOwnProperty(key) &&
|
||||
value !== undefined
|
||||
if (valid === true) {
|
||||
value = serializers[key] ? serializers[key](value) : value
|
||||
value = (stringifiers[key] || stringify)(value)
|
||||
if (value === undefined) continue
|
||||
data += ',"' + key + '":' + value
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function getPrettyStream (opts, prettifier, dest, instance) {
|
||||
if (prettifier && typeof prettifier === 'function') {
|
||||
prettifier = prettifier.bind(instance)
|
||||
return prettifierMetaWrapper(prettifier(opts), dest)
|
||||
}
|
||||
try {
|
||||
var prettyFactory = require('pino-pretty')
|
||||
prettyFactory.asMetaWrapper = prettifierMetaWrapper
|
||||
return prettifierMetaWrapper(prettyFactory(opts), dest)
|
||||
} catch (e) {
|
||||
throw Error('Missing `pino-pretty` module: `pino-pretty` must be installed separately')
|
||||
}
|
||||
}
|
||||
|
||||
function prettifierMetaWrapper (pretty, dest) {
|
||||
var warned = false
|
||||
return {
|
||||
[needsMetadataGsym]: true,
|
||||
lastLevel: 0,
|
||||
lastMsg: null,
|
||||
lastObj: null,
|
||||
lastLogger: null,
|
||||
flushSync () {
|
||||
if (warned) {
|
||||
return
|
||||
}
|
||||
warned = true
|
||||
setMetadataProps(dest, this)
|
||||
dest.write(pretty(Object.assign({
|
||||
level: 40, // warn
|
||||
msg: 'pino.final with prettyPrint does not support flushing',
|
||||
time: Date.now()
|
||||
}, this.chindings())))
|
||||
},
|
||||
chindings () {
|
||||
const lastLogger = this.lastLogger
|
||||
var chindings = null
|
||||
|
||||
// protection against flushSync being called before logging
|
||||
// anything
|
||||
if (!lastLogger) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (lastLogger.hasOwnProperty(parsedChindingsSym)) {
|
||||
chindings = lastLogger[parsedChindingsSym]
|
||||
} else {
|
||||
chindings = JSON.parse('{"v":1' + lastLogger[chindingsSym] + '}')
|
||||
lastLogger[parsedChindingsSym] = chindings
|
||||
}
|
||||
|
||||
return chindings
|
||||
},
|
||||
write (chunk) {
|
||||
const lastLogger = this.lastLogger
|
||||
const chindings = this.chindings()
|
||||
|
||||
var time = this.lastTime
|
||||
|
||||
if (time.match(/^\d+/)) {
|
||||
time = parseInt(time)
|
||||
}
|
||||
|
||||
var lastObj = this.lastObj
|
||||
var errorProps = null
|
||||
|
||||
const obj = Object.assign({
|
||||
level: this.lastLevel,
|
||||
time
|
||||
}, chindings, lastObj, errorProps)
|
||||
|
||||
const serializers = lastLogger[serializersSym]
|
||||
const keys = Object.keys(serializers)
|
||||
var key
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
key = keys[i]
|
||||
if (obj[key] !== undefined) {
|
||||
obj[key] = serializers[key](obj[key])
|
||||
}
|
||||
}
|
||||
|
||||
const stringifiers = lastLogger[stringifiersSym]
|
||||
const redact = stringifiers[redactFmtSym]
|
||||
|
||||
const formatted = pretty(typeof redact === 'function' ? redact(obj) : obj)
|
||||
if (formatted === undefined) return
|
||||
|
||||
setMetadataProps(dest, this)
|
||||
dest.write(formatted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hasBeenTampered (stream) {
|
||||
return stream.write !== stream.constructor.prototype.write
|
||||
}
|
||||
|
||||
function buildSafeSonicBoom (dest, buffer = 0, sync = true) {
|
||||
const stream = new SonicBoom(dest, buffer, sync)
|
||||
stream.on('error', filterBrokenPipe)
|
||||
return stream
|
||||
|
||||
function filterBrokenPipe (err) {
|
||||
// TODO verify on Windows
|
||||
if (err.code === 'EPIPE') {
|
||||
// If we get EPIPE, we should stop logging here
|
||||
// however we have no control to the consumer of
|
||||
// SonicBoom, so we just overwrite the write method
|
||||
stream.write = noop
|
||||
stream.end = noop
|
||||
stream.flushSync = noop
|
||||
stream.destroy = noop
|
||||
return
|
||||
}
|
||||
stream.removeListener('error', filterBrokenPipe)
|
||||
stream.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
function createArgsNormalizer (defaultOptions) {
|
||||
return function normalizeArgs (instance, opts = {}, stream) {
|
||||
// support stream as a string
|
||||
if (typeof opts === 'string') {
|
||||
stream = buildSafeSonicBoom(opts)
|
||||
opts = {}
|
||||
} else if (typeof stream === 'string') {
|
||||
stream = buildSafeSonicBoom(stream)
|
||||
} else if (opts instanceof SonicBoom || opts.writable || opts._writableState) {
|
||||
stream = opts
|
||||
opts = null
|
||||
}
|
||||
opts = Object.assign({}, defaultOptions, opts)
|
||||
if ('extreme' in opts) {
|
||||
throw Error('The extreme option has been removed, use pino.extreme instead')
|
||||
}
|
||||
if ('onTerminated' in opts) {
|
||||
throw Error('The onTerminated option has been removed, use pino.final instead')
|
||||
}
|
||||
if ('changeLevelName' in opts) {
|
||||
process.emitWarning(
|
||||
'The changeLevelName option is deprecated and will be removed in v7. Use levelKey instead.',
|
||||
{ code: 'changeLevelName_deprecation' }
|
||||
)
|
||||
opts.levelKey = opts.changeLevelName
|
||||
delete opts.changeLevelName
|
||||
}
|
||||
const { enabled, prettyPrint, prettifier, messageKey } = opts
|
||||
if (enabled === false) opts.level = 'silent'
|
||||
stream = stream || process.stdout
|
||||
if (stream === process.stdout && stream.fd >= 0 && !hasBeenTampered(stream)) {
|
||||
stream = buildSafeSonicBoom(stream.fd)
|
||||
}
|
||||
if (prettyPrint) {
|
||||
const prettyOpts = Object.assign({ messageKey }, prettyPrint)
|
||||
stream = getPrettyStream(prettyOpts, prettifier, stream, instance)
|
||||
}
|
||||
return { opts, stream }
|
||||
}
|
||||
}
|
||||
|
||||
function final (logger, handler) {
|
||||
if (typeof logger === 'undefined' || typeof logger.child !== 'function') {
|
||||
throw Error('expected a pino logger instance')
|
||||
}
|
||||
const hasHandler = (typeof handler !== 'undefined')
|
||||
if (hasHandler && typeof handler !== 'function') {
|
||||
throw Error('if supplied, the handler parameter should be a function')
|
||||
}
|
||||
const stream = logger[streamSym]
|
||||
if (typeof stream.flushSync !== 'function') {
|
||||
throw Error('final requires a stream that has a flushSync method, such as pino.destination and pino.extreme')
|
||||
}
|
||||
|
||||
const finalLogger = new Proxy(logger, {
|
||||
get: (logger, key) => {
|
||||
if (key in logger.levels.values) {
|
||||
return (...args) => {
|
||||
logger[key](...args)
|
||||
stream.flushSync()
|
||||
}
|
||||
}
|
||||
return logger[key]
|
||||
}
|
||||
})
|
||||
|
||||
if (!hasHandler) {
|
||||
return finalLogger
|
||||
}
|
||||
|
||||
return (err = null, ...args) => {
|
||||
try {
|
||||
stream.flushSync()
|
||||
} catch (e) {
|
||||
// it's too late to wait for the stream to be ready
|
||||
// because this is a final tick scenario.
|
||||
// in practice there shouldn't be a situation where it isn't
|
||||
// however, swallow the error just in case (and for easier testing)
|
||||
}
|
||||
return handler(err, finalLogger, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
function stringify (obj) {
|
||||
try {
|
||||
return JSON.stringify(obj)
|
||||
} catch (_) {
|
||||
return stringifySafe(obj)
|
||||
}
|
||||
}
|
||||
|
||||
function setMetadataProps (dest, that) {
|
||||
if (dest[needsMetadataGsym] === true) {
|
||||
dest.lastLevel = that.lastLevel
|
||||
dest.lastMsg = that.lastMsg
|
||||
dest.lastObj = that.lastObj
|
||||
dest.lastTime = that.lastTime
|
||||
dest.lastLogger = that.lastLogger
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
noop,
|
||||
buildSafeSonicBoom,
|
||||
getPrettyStream,
|
||||
asChindings,
|
||||
asJson,
|
||||
genLog,
|
||||
createArgsNormalizer,
|
||||
final,
|
||||
stringify
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue