Instrument applications with the OpenTelemetry SDK and prove the telemetry is good by validating it against a local Kopai backend. Use when setting up observability, adding tracing/logging/metrics, deciding what to instrument or which attributes to add, retrofitting OTel into an existing codebase, threading context through call chains, configuring sampling, or when traces/logs/metrics aren't appearing after setup. Also use when users say things like "my traces aren't showing up", "I don't see any data", or "how do I add observability to my app". Do NOT use to investigate existing telemetry for a root cause (use root-cause-analysis), to build dashboards (use create-dashboard), or to instrument LLM and agent calls (use otel-genai-instrumentation).
—
—
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
| title | impact | tags |
|---|---|---|
| Node.js Instrumentation | HIGH | lang, nodejs, javascript, traces, logs, metrics |
Set up OpenTelemetry SDK for Node.js applications with automatic instrumentation.
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/apinpm shown — install with the project's own package manager (pnpm add / yarn add),
detected per the package-picking rule in SKILL.md.
Environment Variables:
| Variable | Description |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP endpoint (e.g., http://localhost:4318) |
OTEL_SERVICE_NAME | Service name shown in observability backend |
Create a separate instrumentation file that loads before your application:
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
const sdk = new NodeSDK({
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
// Graceful shutdown
process.on("SIGTERM", () => {
sdk
.shutdown()
.then(() => console.log("Tracing terminated"))
.catch((error) => console.log("Error terminating tracing", error))
.finally(() => process.exit(0));
});# Load instrumentation before your app
node --import ./instrumentation.mjs server.mjsOr in package.json:
{
"type": "module",
"scripts": {
"start": "node --import ./instrumentation.mjs server.mjs"
}
}In a "type": "module" app this patches CommonJS dependencies (they still load through
the require hook). A dependency published as native ESM bypasses that hook and
additionally needs OTel's experimental loader hook:
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs \
--import ./instrumentation.mjs server.mjsThe auto-instrumentation automatically captures:
The SDK auto-detects OTEL_EXPORTER_OTLP_ENDPOINT and exports via OTLP HTTP.
getNodeAutoInstrumentations() covers Express, Koa, Hapi, and most HTTP/DB clients. It
does not cover Fastify — that instrumentation moved to the Fastify team
(@fastify/otel) and the deprecated contrib package was removed from the bundle in
March 2026. Fastify app → lang-fastify.md, which registers a plugin instead of
relying on module interception.
See the complete working example: kopai-integration-examples/node-js
SDK setup is step 3 of six. It gets bytes flowing; it does not make the telemetry good.
instrument-spans.mdinstrument-attributes.mdinstrument-errors.mddrive-traffic.mdvalidate-traces.mdConfirm before moving on: the SDK starts before any application code that could
create a span, and shutdown flushes on SIGTERM (validate-shutdown.md). Both fail
silently.
references