in packages/ecs-pino-format/index.js [35:212]
function ecsFormat (opts) {
// istanbul ignore next
opts = opts || {}
const convertErr = opts.convertErr != null ? opts.convertErr : true
const convertReqRes = opts.convertReqRes != null ? opts.convertReqRes : false
const apmIntegration = opts.apmIntegration != null ? opts.apmIntegration : true
let apm = null
if (apmIntegration) {
// istanbul ignore if
if (opts && opts._elasticApm) {
// `opts._elasticApm` is an internal/testing-only option to be used
// for testing in the APM agent where the import is a local path
// rather than "elastic-apm-node".
elasticApm = opts._elasticApm
} else if (!triedElasticApmImport) {
triedElasticApmImport = true
// We lazily require this module here instead of at the top-level to
// avoid a possible circular-require if the user code does
// `require('@elastic/ecs-pino-format')` and has a "node_modules/"
// where 'elastic-apm-node' shares the same ecs-pino-format install.
try {
elasticApm = require('elastic-apm-node')
} catch (ex) {
// Silently ignore.
}
}
if (elasticApm && elasticApm.isStarted && elasticApm.isStarted()) {
apm = elasticApm
}
}
let serviceName = opts.serviceName
if (serviceName == null && apm) {
// istanbul ignore next
serviceName = (apm.getServiceName
? apm.getServiceName() // added in elastic-apm-node@3.11.0
: apm._conf.serviceName) // fallback to private `_conf`
}
let serviceVersion = opts.serviceVersion
// istanbul ignore next
if (serviceVersion == null && apm) {
serviceVersion = (apm.getServiceVersion
? apm.getServiceVersion() // added in elastic-apm-node@...
: apm._conf.serviceVersion) // fallback to private `_conf`
}
let serviceEnvironment = opts.serviceEnvironment
if (serviceEnvironment == null && apm) {
// istanbul ignore next
serviceEnvironment = (apm.getServiceEnvironment
? apm.getServiceEnvironment() // added in elastic-apm-node@...
: apm._conf.environment) // fallback to private `_conf`
}
let serviceNodeName = opts.serviceNodeName
if (serviceNodeName == null && apm) {
// istanbul ignore next
serviceNodeName = (apm.getServiceNodeName
? apm.getServiceNodeName() // added in elastic-apm-node@...
: apm._conf.serviceNodeName) // fallback to private `_conf`
}
let eventDataset = opts.eventDataset
if (eventDataset == null && serviceName) {
eventDataset = serviceName
}
let wasBindingsCalled = false
function addStaticEcsBindings (obj) {
obj['ecs.version'] = version
if (serviceName) { obj['service.name'] = serviceName }
if (serviceVersion) { obj['service.version'] = serviceVersion }
if (serviceEnvironment) { obj['service.environment'] = serviceEnvironment }
if (serviceNodeName) { obj['service.node.name'] = serviceNodeName }
if (eventDataset) { obj['event.dataset'] = eventDataset }
}
const ecsPinoOptions = {
messageKey: 'message',
timestamp: () => `,"@timestamp":"${new Date().toISOString()}"`,
formatters: {
level (label, number) {
return { 'log.level': label }
},
bindings (bindings) {
const {
// `pid` and `hostname` are default bindings, unless overriden by
// a `base: {...}` passed to logger creation.
pid,
hostname,
// name is defined if `log = pino({name: 'my name', ...})`
name,
...ecsBindings
} = bindings
if (pid !== undefined) {
// https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-pid
ecsBindings['process.pid'] = pid
}
if (hostname !== undefined) {
// https://www.elastic.co/guide/en/ecs/current/ecs-host.html#field-host-hostname
ecsBindings['host.hostname'] = hostname
}
if (name !== undefined) {
// https://www.elastic.co/guide/en/ecs/current/ecs-log.html#field-log-logger
ecsBindings['log.logger'] = name
}
// With `pino({base: null, ...})` the `formatters.bindings` is *not*
// called. In this case we need to make sure to add our static bindings
// in `log()` below.
wasBindingsCalled = true
addStaticEcsBindings(ecsBindings)
return ecsBindings
},
log (obj) {
const {
req,
res,
err,
...ecsObj
} = obj
if (!wasBindingsCalled) {
addStaticEcsBindings(ecsObj)
}
if (apm) {
// https://www.elastic.co/guide/en/ecs/current/ecs-tracing.html
const tx = apm.currentTransaction
if (tx) {
ecsObj['trace.id'] = tx.traceId
ecsObj['transaction.id'] = tx.id
const span = apm.currentSpan
// istanbul ignore else
if (span) {
ecsObj['span.id'] = span.id
}
}
}
// https://www.elastic.co/guide/en/ecs/current/ecs-http.html
if (err !== undefined) {
if (!convertErr) {
ecsObj.err = err
} else {
formatError(ecsObj, err)
}
}
// https://www.elastic.co/guide/en/ecs/current/ecs-http.html
if (req !== undefined) {
if (!convertReqRes) {
ecsObj.req = req
} else {
formatHttpRequest(ecsObj, req)
}
}
if (res !== undefined) {
if (!convertReqRes) {
ecsObj.res = res
} else {
formatHttpResponse(ecsObj, res)
}
}
return ecsObj
}
}
}
return ecsPinoOptions
}