How-to · OpenTelemetry

How to Instrument Node.js Apps with OpenTelemetry

Instrumenting Node.js with OpenTelemetry means adding the OpenTelemetry Node SDK and auto-instrumentation so your application emits traces, metrics and logs over OTLP with little or no code change..

Instrumenting Node.js with OpenTelemetry means adding the OpenTelemetry Node SDK and auto-instrumentation so your application emits traces, metrics and logs over OTLP with little or no code change.

What to observe in a Node.js service

A Node.js service has two failure surfaces, and they need different signals. The request surface is what your users feel: latency and error rate per route, and the latency of every downstream call the request makes to a database or another API. The runtime surface is unique to Node's single-threaded, event-loop model: if the event loop is blocked by synchronous CPU work, every in-flight request stalls at once, which no per-route metric alone will explain.

So a complete picture is per-route HTTP timing and errors, downstream span latency, and the Node runtime health, event-loop lag, heap usage against the limit, and garbage-collection pauses, plus unhandled exceptions and rejections that would otherwise crash or silently degrade the process.

How OpenTelemetry collects it

Node.js has strong zero-code instrumentation. The @opentelemetry/auto-instrumentations-node package patches the common libraries, the HTTP server and client, Express or Fastify, gRPC, and popular database and cache clients, so every inbound request becomes a span and every downstream call a child span, with no edits to your application. You register it before your app loads, typically through Node's --require flag or NODE_OPTIONS, and point the OTLP exporter at your Collector.

Auto-instrumentation covers the request surface; the runtime surface needs the runtime-metrics instrumentation, which emits event-loop and heap and GC metrics from V8. Add manual spans only where your own business logic does work the libraries cannot see. The one detail that matters for correlation is context propagation: as long as the auto-instrumentation is active, the trace context flows across async boundaries and outbound calls, so a slow request links to the exact downstream span that caused it.

Metric and attribute names below follow the OpenTelemetry semantic conventions and can shift between instrumentation versions, so confirm the exact identifiers against the version you deploy.

Key metrics to watch

These are the signals that explain almost every Node.js incident:

SignalSourceWhat it tells you / watch for
http.server.request.durationHTTP instrumentationPer-route latency histogram. Track p95/p99 by route; a single slow route rarely means the whole service is slow.
error rate (http.server.request.duration count where status >= 500)HTTP instrumentation5xx responses per route. Correlate with a downstream span or a recent deploy.
nodejs.eventloop.utilization / event-loop lagruntime instrumentationThe Node-specific tell. Rising lag means synchronous work is blocking the loop and stalling every request.
v8js.memory.heap.used vs heap limitruntime instrumentationHeap climbing steadily toward the limit is a leak; the process will eventually crash or GC-thrash.
v8js.gc.durationruntime instrumentationLong or frequent GC pauses freeze the event loop and show up as latency spikes.
downstream span durationclient instrumentationLatency of DB and API calls inside a request; usually where a slow request's time actually goes.

What to put on a dashboard

A Node.js dashboard should let you decide in seconds whether a latency problem is in your code, in the runtime, or in a dependency. Row one is request health: p95 and p99 latency by route and 5xx rate by route. Row two is the runtime: event-loop lag, heap used against the limit, and GC pause time, the three panels that reveal blocking, leaks and GC pressure respectively. Row three is dependencies: p95 latency of outbound calls grouped by target, so a slow database or upstream API is obvious at a glance.

# p99 latency by route (find the slow endpoint, not just "the service")
histogram_quantile(0.99, http.server.request.duration) by (http.route)

# event-loop lag: the Node-specific blocking signal
nodejs.eventloop.utilization

# heap headroom: used / limit climbing toward 1.0 = leak
v8js.memory.heap.used / v8js.memory.heap.limit

Reading the signals: common failure modes

Event loop blocked

Every route slows simultaneously while CPU sits high on one thread. The cause is synchronous work on the request path, a large JSON parse, sync crypto, a tight loop. Event-loop lag spikes while downstream spans look fine, which is how you tell blocking apart from a slow dependency. Move the work off the loop or into a worker thread.

Memory leak

Heap used climbs release over release and never fully drops after GC, ending in an out-of-memory crash or constant GC. Watch v8js.memory.heap.used trend across deploys; a monotonic climb is the signature. Common culprits are unbounded caches and listeners that are never removed.

Slow dependency

One route's p99 rises and its downstream span, a specific query or API call, accounts for the added time. The runtime panels stay healthy. The fix lives in the dependency, not the Node process.

Example alert conditions

Reasonable starting thresholds to tune to your SLOs:

ConditionSignalMeaning
5xx rate by route > 2% for 5merrorsA route is failing, not just slow.
p99 http.server.request.duration > your SLO for 10mlatencySustained latency regression on a route.
event-loop lag > 100ms for 2mruntimeThe loop is blocked; requests are queueing.
heap used / limit > 0.9 for 10mmemoryLeak or undersized heap; crash risk.

From monitoring to autonomous resolution

Ops Singularity's TelemetryOps ingests your Node.js OpenTelemetry data natively, and Sentinel AI resolves the service incidents it reveals through governed Action Tickets validated by Sherlock. Explore TelemetryOps and ServiceOps.

Frequently asked questions

How do I add OpenTelemetry to a Node.js app?

Install the OpenTelemetry Node SDK and @opentelemetry/auto-instrumentations-node, register it before your application loads, and configure the OTLP exporter to send traces and metrics to an OpenTelemetry Collector.

Does OpenTelemetry auto-instrument Node.js?

Yes. The auto-instrumentations-node package patches common libraries like HTTP, Express and popular database clients, so you get traces and metrics with little or no code change.

See autonomous operations on your own stack.

Bring a real incident. We will show you Sentinel investigate, act and verify end to end, with every action reversible and audited.

Request a Demo → See TelemetryOps