Socket
Socket
Sign inDemoInstall

@elastic/ecs-pino-format

Package Overview
Dependencies
11
Maintainers
57
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.3.0 to 1.4.0

25

index.d.ts

@@ -8,2 +8,3 @@ import type { LoggerOptions } from "pino";

*/
convertErr?: boolean;

@@ -14,3 +15,5 @@ /**

*/
convertReqRes?: boolean;
/**

@@ -22,10 +25,28 @@ * Whether to automatically integrate with

*
* - "service.name" - the configured serviceName in the agent
* - "event.dataset" - set to "$serviceName.log" for correlation in Kibana
* - "trace.id", "transaction.id", and "span.id" - if there is a current
* active trace when the log call is made
*
* and also the following fields, if not already specified in this config:
*
* - "service.name" - the configured `serviceName` in the agent
* - "service.version" - the configured `serviceVersion` in the agent
* - "service.environment" - the configured `environment` in the agent
* - "service.node.name" - the configured `serviceNodeName` in the agent
* - "event.dataset" - set to `${serviceName}` for correlation in Kibana
*
* Default true.
*/
apmIntegration?: boolean;
/** Specify "service.name" field. Defaults to a value from the APM agent, if available. */
serviceName?: string;
/** Specify "service.version" field. Defaults to a value from the APM agent, if available. */
serviceVersion?: string;
/** Specify "service.environment" field. Defaults to a value from the APM agent, if available. */
serviceEnvironment?: string;
/** Specify "service.node.name" field. Defaults to a value from the APM agent, if available. */
serviceNodeName?: string;
/** Specify "event.dataset" field. Defaults `${serviceName}`. */
eventDataset?: string;
}

@@ -32,0 +53,0 @@

181

index.js

@@ -27,42 +27,18 @@ // Licensed to Elasticsearch B.V. under one or more contributor

const { hasOwnProperty } = Object.prototype
let triedElasticApmImport = false
let elasticApm = null
// Create options for `pino(...)` that configure it for ecs-logging output.
//
// @param {Object} opts - Optional.
// - {Boolean} opts.convertErr - Whether to convert a logged `err` field
// to ECS error fields. Default true, to match Pino's default of having
// an `err` serializer.
// - {Boolean} opts.convertReqRes - Whether to convert logged `req` and `res`
// HTTP request and response fields to ECS HTTP, User agent, and URL
// fields. Default false.
// - {Boolean} opts.apmIntegration - Whether to automatically integrate with
// Elastic APM (https://github.com/elastic/apm-agent-nodejs). If a started
// APM agent is detected, then log records will include the following
// fields:
// - "service.name" - the configured serviceName in the agent
// - "event.dataset" - set to "$serviceName.log" for correlation in Kibana
// - "trace.id", "transaction.id", and "span.id" - if there is a current
// active trace when the log call is made
// Default true.
/**
* Create options for `pino(...)` that configure it for ecs-logging output.
*
* @param {Config} [opts] - See index.d.ts.
*/
function createEcsPinoOptions (opts) {
let convertErr = true
let convertReqRes = false
let apmIntegration = true
if (opts) {
if (hasOwnProperty.call(opts, 'convertErr')) {
convertErr = opts.convertErr
}
if (hasOwnProperty.call(opts, 'convertReqRes')) {
convertReqRes = opts.convertReqRes
}
if (hasOwnProperty.call(opts, 'apmIntegration')) {
apmIntegration = opts.apmIntegration
}
}
// 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
let apmServiceName = null
if (apmIntegration) {

@@ -89,13 +65,52 @@ // istanbul ignore if

apm = elasticApm
// Elastic APM v3.11.0 added getServiceName(). Fallback to private `apm._conf`.
// istanbul ignore next
apmServiceName = apm.getServiceName
? apm.getServiceName()
: apm._conf.serviceName
}
}
let isServiceNameInBindings = false
let isEventDatasetInBindings = false
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
if (serviceVersion == null && apm) {
// istanbul ignore next
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 = {

@@ -117,5 +132,2 @@ messageKey: 'message',

name,
// Warning: silently drop any "ecs" value from `base`. See
// "ecs.version" comment below.
ecs,
...ecsBindings

@@ -126,20 +138,18 @@ } = bindings

// https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-pid
ecsBindings.process = { pid: 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 }
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 }
ecsBindings['log.logger'] = name
}
// Note if service.name & event.dataset are set, to not do so again below.
if (bindings.service && bindings.service.name) {
isServiceNameInBindings = true
}
if (bindings.event && bindings.event.dataset) {
isEventDatasetInBindings = true
}
// 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)

@@ -157,52 +167,16 @@ return ecsBindings

// https://www.elastic.co/guide/en/ecs/current/ecs-ecs.html
// For "ecs.version" we take a heavier-handed approach, because it is
// a require ecs-logging field: overwrite any possible "ecs" value from
// the log statement. This means we don't need to spend the time
// guarding against "ecs" being null, Array, Buffer, Date, etc.
ecsObj.ecs = { version }
if (!wasBindingsCalled) {
addStaticEcsBindings(ecsObj)
}
if (apm) {
// A mis-configured APM Agent can be "started" but not have a
// "serviceName".
if (apmServiceName) {
// Per https://github.com/elastic/ecs-logging/blob/master/spec/spec.json
// "service.name" and "event.dataset" should be automatically set
// if not already by the user.
if (!isServiceNameInBindings) {
const service = ecsObj.service
if (service === undefined) {
ecsObj.service = { name: apmServiceName }
} else if (!isVanillaObject(service)) {
// Warning: "service" type conflicts with ECS spec. Overwriting.
ecsObj.service = { name: apmServiceName }
} else if (typeof service.name !== 'string') {
ecsObj.service.name = apmServiceName
}
}
if (!isEventDatasetInBindings) {
const event = ecsObj.event
if (event === undefined) {
ecsObj.event = { dataset: apmServiceName + '.log' }
} else if (!isVanillaObject(event)) {
// Warning: "event" type conflicts with ECS spec. Overwriting.
ecsObj.event = { dataset: apmServiceName + '.log' }
} else if (typeof event.dataset !== 'string') {
ecsObj.event.dataset = apmServiceName + '.log'
}
}
}
// https://www.elastic.co/guide/en/ecs/current/ecs-tracing.html
const tx = apm.currentTransaction
if (tx) {
ecsObj.trace = ecsObj.trace || {}
ecsObj.trace.id = tx.traceId
ecsObj.transaction = ecsObj.transaction || {}
ecsObj.transaction.id = tx.id
ecsObj['trace.id'] = tx.traceId
ecsObj['transaction.id'] = tx.id
const span = apm.currentSpan
// istanbul ignore else
if (span) {
ecsObj.span = ecsObj.span || {}
ecsObj.span.id = span.id
ecsObj['span.id'] = span.id
}

@@ -245,17 +219,2 @@ }

// Return true if the given arg is a "vanilla" object. Roughly the intent is
// whether this is basic mapping of string keys to values that will serialize
// as a JSON object.
//
// Currently, it excludes Map. The uses above don't really expect a user to:
// service = new Map([["foo", "bar"]])
// log.info({ service }, '...')
//
// There are many ways tackle this. See some attempts and benchmarks at:
// https://gist.github.com/trentm/34131a92eede80fd2109f8febaa56f5a
function isVanillaObject (o) {
return (typeof o === 'object' &&
(!o.constructor || o.constructor.name === 'Object'))
}
module.exports = createEcsPinoOptions
{
"name": "@elastic/ecs-pino-format",
"version": "1.3.0",
"version": "1.4.0",
"description": "A formatter for the pino logger compatible with Elastic Common Schema.",

@@ -31,5 +31,7 @@ "main": "index.js",

},
"homepage": "https://github.com/elastic/ecs-logging-nodejs/blob/master/loggers/pino/README.md",
"homepage": "https://github.com/elastic/ecs-logging-nodejs/blob/main/loggers/pino/README.md",
"scripts": {
"test": "standard && tap --100 --timeout ${TAP_TIMEOUT:-10} test/*.test.js"
"lint": "standard",
"lint:fix": "standard --fix",
"test": "tap --timeout ${TAP_TIMEOUT:-10} test/*.test.js"
},

@@ -46,3 +48,3 @@ "engines": {

"ajv-formats": "^1.5.1",
"elastic-apm-node": "^3.14.0",
"elastic-apm-node": "^3.23.0",
"express": "^4.17.1",

@@ -53,4 +55,4 @@ "pino": "^6.0.0",

"standard": "16.x",
"tap": "^14.x"
"tap": "^15.0.10"
}
}

@@ -5,3 +5,3 @@ <img align="right" width="auto" height="auto" src="https://www.elastic.co/static-res/images/elastic-logo-200.png">

[![Build Status](https://apm-ci.elastic.co/buildStatus/icon?job=apm-agent-nodejs%2Fecs-logging-nodejs-mbp%2Fmaster)](https://apm-ci.elastic.co/job/apm-agent-nodejs/job/ecs-logging-nodejs-mbp/job/master/) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
[![Build Status](https://apm-ci.elastic.co/buildStatus/icon?job=apm-agent-nodejs%2Fecs-logging-nodejs-mbp%2Fmain)](https://apm-ci.elastic.co/job/apm-agent-nodejs/job/ecs-logging-nodejs-mbp/job/main/) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)

@@ -32,3 +32,3 @@ This Node.js package provides a formatter for the [pino](https://www.npmjs.com/package/pino)

const log = pino(ecsFormat())
const log = pino(ecsFormat(/* options */))
log.info('Hello world')

@@ -43,4 +43,4 @@

```sh
{"log.level":"info","@timestamp":"2021-01-19T22:51:12.142Z","ecs":{"version":"1.6.0"},"process":{"pid":82240},"host":{"hostname":"pink.local"},"message":"Hello world"}
{"log.level":"warn","@timestamp":"2021-01-19T22:51:12.143Z","ecs":{"version":"1.6.0"},"process":{"pid":82240},"host":{"hostname":"pink.local"},"module":"foo","message":"From child"}
{"log.level":"info","@timestamp":"2023-10-16T18:08:02.601Z","process.pid":74325,"host.hostname":"pink.local","ecs.version":"1.6.0","message":"Hello world"}
{"log.level":"warn","@timestamp":"2023-10-16T18:08:02.602Z","process.pid":74325,"host.hostname":"pink.local","ecs.version":"1.6.0","module":"foo","message":"From child"}
```

@@ -47,0 +47,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc