@elastic/opentelemetry-node

Elastic's zero-code OpenTelemetry distribution for Node.js, giving production apps tracing, metrics, and logs with a single --import flag.

Tool
npm
v1.18.0
12stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
70/100Good
Development Activity96
Maintenance100
Community24
Maturity48
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture76
Code Quality78
Innovation62
Learning Curve90

EDOT Node.js (@elastic/opentelemetry-node) is Elastic’s distribution of the OpenTelemetry SDK for Node.js. Rather than reimplementing tracing, metrics, or log collection, it wraps @opentelemetry/sdk-node and bundles dozens of first-party OpenTelemetry instrumentation packages (HTTP, Express, Fastify, Koa, Postgres, MongoDB, Redis, Kafka, AWS SDK, and many more) so a Node.js application gets full auto-instrumentation by adding one line to its start command: node --import @elastic/opentelemetry-node app.js.

Beyond bundling upstream OpenTelemetry packages, the distribution adds Elastic-specific behavior: dynamic central configuration (letting an Elastic backend adjust sampling and other SDK settings at runtime without redeploying), extra resource detectors, host-metrics collection enabled by default, a custom JSON-formatted diagnostic logger, and OTLP exporters wired up out of the box. It is designed to be a drop-in path to Elastic Observability while remaining a standard, spec-compliant OpenTelemetry SDK underneath.

The package is part of a small monorepo alongside @elastic/opamp-client-node (an OpAMP protocol client used for the central-configuration channel) and mock OTLP/OpAMP servers used in the project’s own test suite.

What You Get

  • Zero-code instrumentation activated with a single node --import @elastic/opentelemetry-node flag, no manual SDK wiring required
  • Dozens of bundled OpenTelemetry instrumentation packages covering HTTP frameworks (Express, Fastify, Koa, Hapi, Restify), databases (Postgres, MySQL, MongoDB, Redis, Cassandra, Oracle), messaging (AWS SQS/SNS, Kafka, AMQP), and logging frameworks (Pino, Winston, Bunyan)
  • Dynamic central configuration via an OpAMP client, letting sampling and other settings be adjusted from an Elastic backend without redeploying the app
  • Default OTLP exporters for traces, metrics, and logs (gRPC, HTTP, and protobuf variants) configured from standard OTEL_EXPORTER_OTLP_* environment variables
  • Host metrics collection enabled by default via @opentelemetry/instrumentation-host-metrics, unlike the upstream auto-instrumentations package
  • A /sdk subpath export for programmatic (in-code) SDK setup when the CLI-flag approach doesn’t fit the deployment model

Common Use Cases

  • Adding distributed tracing and metrics to an existing Node.js service shipping telemetry to Elastic Observability, without touching application code
  • Standardizing OpenTelemetry instrumentation across many Node.js microservices where each team would otherwise hand-roll SDK setup and pick a different subset of instrumentations
  • Running EDOT Node.js inside a Kubernetes pod via the OpenTelemetry Operator’s auto-instrumentation injection, using the bundled autoinstrumentation.js entry point
  • Getting host-level metrics (CPU, memory, event loop lag) alongside request tracing in one dependency instead of assembling several packages manually
  • Migrating from @opentelemetry/auto-instrumentations-node to a distribution with dynamic central configuration and Elastic-specific defaults

Under The Hood

Architecture The package’s entry points (import.mjs, require.js, hook.mjs) are thin bootstrap shims that call into lib/sdk.js, which assembles and starts an @opentelemetry/sdk-node NodeSDK instance. Supporting modules under lib/ each own one concern: instrumentations.js builds the list of enabled instrumentation instances from environment configuration, detectors.js resolves resource detectors, central-config.js and dynconf.js implement the OpAMP-driven dynamic configuration channel that can swap exporters and samplers at runtime, environment.js manages EDOT-specific environment variable handling (including scrubbing them before user code sees them), and logging.js/luggite.js implement the custom diagnostic logger. This is a layered, single-responsibility module structure rather than a monolith, and the OpAMP-based dynamic reconfiguration is the one piece of real architectural complexity — most other modules are straightforward composition over upstream OpenTelemetry APIs.

Tech Stack Plain CommonJS Node.js (with an ESM entry point for --import usage), no build step or transpilation for the runtime code — TypeScript is used only to generate the published .d.ts type declarations from JSDoc-annotated source (tsc --outDir under gen:types). It depends directly on @opentelemetry/sdk-node, @opentelemetry/core, @opentelemetry/sdk-logs, and a long list of @opentelemetry/instrumentation-* packages, plus import-in-the-middle for ESM module hooking and its own sibling package @elastic/opamp-client-node for the central-config protocol. Supports Node.js ^18.19 or >=20.6.

Code Quality Tests use tape (not a heavier framework like Jest/Vitest) with fixtures and Docker Compose-backed integration tests (test-services:start) exercising real databases and brokers rather than mocks alone — 45+ test files cover individual instrumentations, ESM usage, central config, and host metrics. Linting runs ESLint, Prettier, tsc type-checking against hand-written .d.ts files, a dependency-check step (lint:deps), and a license-file/changelog linter, all wired into CI via GitHub Actions (lint.yml, test-edot.yml). JSDoc type annotations stand in for TypeScript source, which is a deliberate but unusual choice for a package of this size.

What Makes It Unique What differentiates this from the upstream @opentelemetry/auto-instrumentations-node package it closely tracks is the OpAMP-based dynamic central configuration channel, letting an operator adjust sampling and other SDK behavior for a running fleet of services without redeploying, plus defaults tuned for the Elastic backend (delta temporality, host metrics on by default, a distro-identifying resource attribute, and a structured JSON diagnostic log format). It is a distribution in the OpenTelemetry sense — same spec, curated defaults and an extra control-plane feature — rather than a from-scratch reimplementation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search