Skip to main content

OpenTelemetry for Node.js

OpenTelemetry for Node.js supports zero-code instrumentation through a single --require flag (or NODE_OPTIONS) — it auto-wires HTTP, Express, Fastify, Koa, MongoDB, Postgres, MySQL, Redis, gRPC, and most other popular libraries on startup. Traces ship to CodeXray over OTLP.

Two ways to start tracing

Zero-code (recommended for most apps) — install one package, prepend a --require flag to your start command, set four env vars. No source changes.

Programmatic — if you need fine control or you're shipping a Next.js / NestJS / similar framework with a custom bootstrap, instantiate the SDK in code. See the Next.js doc for the framework-specific path.


Before You Begin​

You'll need:

  • A Node.js application (Node.js 18+)
  • The URL of your CodeXray collector (e.g., https://your-codexray.example.com)
  • A project API key from the CodeXray UI (Project Settings → API Keys)

Step 1 — Install the OpenTelemetry Packages​

npm install \
@opentelemetry/api \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-proto
PackageWhat it does
@opentelemetry/apiThe core OTel API — used by libraries and your own code to create spans
@opentelemetry/auto-instrumentations-nodeBundle of every auto-instrumentation library (HTTP, Express, Fastify, Postgres, MongoDB, Redis, …). Picks the ones that match what your app imports.
@opentelemetry/exporter-trace-otlp-protoOTLP HTTP/protobuf exporter — ships spans to your CodeXray collector

Step 2 — Configure via Environment Variables​

export OTEL_SERVICE_NAME="your-service-name"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://your-codexray.example.com"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-project-api-key"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
VariablePurpose
OTEL_SERVICE_NAMEThe name that appears in CodeXray's Applications list
OTEL_EXPORTER_OTLP_ENDPOINTYour CodeXray collector URL (no trailing slash)
OTEL_EXPORTER_OTLP_PROTOCOLhttp/protobuf (recommended) or grpc
OTEL_EXPORTER_OTLP_HEADERSAuthentication — your project API key as x-api-key
OTEL_RESOURCE_ATTRIBUTESOptional — deployment.environment=production,service.version=1.3.0

Step 3 — Run with Auto-Instrumentation​

Prepend --require @opentelemetry/auto-instrumentations-node/register to your start command:

node --require @opentelemetry/auto-instrumentations-node/register server.js

For npm scripts, update package.json:

{
"scripts": {
"start": "node --require @opentelemetry/auto-instrumentations-node/register server.js"
}
}

Using NODE_OPTIONS instead of --require​

If you can't change the start command (PaaS, hosted runtimes), set the same thing via env:

export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
node server.js # picks it up automatically

NODE_OPTIONS is the right choice for Docker images where the CMD is fixed and you only control env vars.


What Gets Instrumented Automatically​

The auto-instrumentations-node bundle includes coverage for the most common libraries — and the SDK only activates the ones your app actually imports:

LayerLibraries covered
HTTP servershttp, https, express, fastify, koa, hapi, restify
HTTP clientshttp, https, axios, undici (Node 18+ fetch), got
Databasespg, mysql, mysql2, mongodb, mongoose, redis, ioredis
Messagingamqplib (RabbitMQ), kafkajs, aws-sdk (SQS, SNS, DynamoDB)
GraphQLgraphql, apollo-server, apollo-client
RPCgrpc-js, connect

Each instrumentation produces a span per call — request method + route for HTTP, query text for SQL, command for Redis, etc.


Verifying It's Working​

  1. Start your service with the --require flag (or NODE_OPTIONS) and the OTel env vars set
  2. Hit an instrumented endpoint
  3. In CodeXray, open Applications → find your service → Traces tab
  4. Traces should appear within a minute, named by HTTP method + route

If nothing arrives, enable debug logging:

export OTEL_LOG_LEVEL="debug"

The SDK then prints every exported span batch and any HTTP error from the collector to stdout.


Custom Spans for Business Logic​

Auto-instrumentation covers framework and library calls — for your own functions, add spans manually:

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

const tracer = trace.getTracer('my-service');

async function processOrder(orderId) {
return tracer.startActiveSpan('processOrder', async (span) => {
span.setAttribute('order.id', orderId);
try {
// your business logic ...
} finally {
span.end();
}
});
}

The new span automatically becomes a child of whatever HTTP request span is currently active.


Disabling a Specific Instrumentation​

If you don't want a particular library traced (e.g. redis is too chatty), disable it via env:

export OTEL_NODE_DISABLED_INSTRUMENTATIONS="redis,ioredis"

The bundle still loads but skips those instrumentation modules.


Next Steps​