Skip to content

Node.js ​

Automatic traces, metrics and logs for Express, Fastify, NestJS, Koa, Next.js, http, fetch, Postgres, MySQL, Redis, MongoDB and more, with no code changes.

Prerequisites

An OpenTelemetry Stream and an ingest key for that Stream. See OpenTelemetry → Prerequisites.

1. Install ​

bash
npm install @opentelemetry/api @opentelemetry/auto-instrumentations-node

2. Configure ​

Add these to the environment (or .env):

bash
OTEL_SERVICE_NAME=checkout-api
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=https://ws.latency.app/v1/ingest
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20lit_XXXXXXXXXXX
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta

Only sending traces? Add OTEL_METRICS_EXPORTER=none and OTEL_LOGS_EXPORTER=none.

3. Run ​

Load the instrumentation before the app starts:

bash
node --require @opentelemetry/auto-instrumentations-node/register app.js

Can't change the start command? Set it in the environment instead:

bash
NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"

Using .env files?

The SDK reads configuration while loading, before the app parses .env. Load the file first with Node's built-in flag: node --env-file=.env --require @opentelemetry/auto-instrumentations-node/register app.js

4. Check it's working ​

Make a few requests to the app, then open Telemetry in the Console, pick the Stream and choose Traces. Traces show up within seconds. Metrics follow within a minute.

Custom spans ​

Wrap any work that should appear in a trace:

js
import { trace } from '@opentelemetry/api';

const tracer = trace.getTracer('checkout');

await tracer.startActiveSpan('charge-card', async (span) => {
  try {
    span.setAttribute('order.id', order.id);
    await chargeCard(order);
  } finally {
    span.end();
  }
});

Custom metrics ​

js
import { metrics } from '@opentelemetry/api';

const meter = metrics.getMeter('checkout');
const orders = meter.createCounter('orders.placed');
const duration = meter.createHistogram('checkout.duration', { unit: 'ms' });

orders.add(1, { plan: 'pro' });
duration.record(182, { route: '/pay' });

Logs ​

Logs written with pino or bunyan are sent automatically, with the trace they belong to. For winston, also install the transport:

bash
npm install @opentelemetry/winston-transport

ES modules ​

Using "type": "module" or .mjs? Add OpenTelemetry's loader hook so imported libraries get instrumented too:

bash
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs \
  --import @opentelemetry/auto-instrumentations-node/register app.js

More in OpenTelemetry's ESM support notes.

© 2026 Latency Labs LLC