OpenTelemetry SDK Setup
Initialize the OpenTelemetry Node.js SDK with resource attributes, exporters, and auto-instrumentation
When to Use
- Setting up OpenTelemetry in a new Node.js application
- Migrating from vendor-specific SDKs (Datadog, New Relic) to OpenTelemetry
- Configuring auto-instrumentation for HTTP, database, and framework libraries
- Establishing the telemetry foundation before adding custom spans and metrics
Instructions
- Install the core SDK and auto-instrumentation packages.
- Create the instrumentation file (
instrumentation.ts) — it must run before any other application code. - Define the resource with service name, version, and environment.
- Configure exporters for traces, metrics, and logs (OTLP is the standard protocol).
- Register auto-instrumentations for libraries your application uses.
- Load the instrumentation file first:
node --require ./instrumentation.tsorimport './instrumentation'at the top of your entry point.
npm install @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/exporter-metrics-otlp-http \
@opentelemetry/resources \
@opentelemetry/semantic-conventions
// instrumentation.ts — must be loaded before application code
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { Resource } from '@opentelemetry/resources';
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
ATTR_DEPLOYMENT_ENVIRONMENT,
} from '@opentelemetry/semantic-conventions';
const resource = new Resource({
[ATTR_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || 'my-service',
[ATTR_SERVICE_VERSION]: process.env.npm_package_version || '0.0.0',
[ATTR_DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV || 'development',
});
const sdk = new NodeSDK({
resource,
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/metrics',
}),
exportIntervalMillis: 15000,
}),
instrumentations: [
getNodeAutoInstrumentations({
// Disable noisy instrumentations
'@opentelemetry/instrumentation-fs': { enabled: false },
'@opentelemetry/instrumentation-dns': { enabled: false },
}),
],
});
sdk.start();
// Graceful shutdown
process.on('SIGTERM', () => {
sdk.shutdown().then(
() => console.log('Telemetry shut down'),
(err) => console.error('Telemetry shutdown error', err)
);
});
// package.json — load instrumentation first
{
"scripts": {
"start": "node --require ./dist/instrumentation.js ./dist/index.js",
"dev": "tsx --require ./src/instrumentation.ts ./src/index.ts"
}
}
Details
Load order is critical. OpenTelemetry hooks into library internals (HTTP, pg, express) by monkey-patching. If you import express before OpenTelemetry initializes, the instrumentation will not work. Always load instrumentation.ts first.
Auto-instrumentations included:
@opentelemetry/instrumentation-http— HTTP/HTTPS client and server@opentelemetry/instrumentation-express— Express routes and middleware@opentelemetry/instrumentation-pg— PostgreSQL queries@opentelemetry/instrumentation-redis— Redis commands@opentelemetry/instrumentation-mongodb— MongoDB operations@opentelemetry/instrumentation-grpc— gRPC calls- And many more via
auto-instrumentations-node
Environment variables (standard):
OTEL_SERVICE_NAME— service name (overrides code)OTEL_EXPORTER_OTLP_ENDPOINT— collector URLOTEL_EXPORTER_OTLP_PROTOCOL—grpcorhttp/protobufOTEL_TRACES_SAMPLER—always_on,always_off,traceidratioOTEL_TRACES_SAMPLER_ARG— sampler argument (e.g.,0.1for 10%)
Local development: Run the OpenTelemetry Collector and Jaeger locally:
docker run -d -p 4318:4318 -p 16686:16686 jaegertracing/all-in-one:latest
Then view traces at http://localhost:16686.
Common mistakes:
- Importing the instrumentation file after application modules
- Not calling
sdk.shutdown()on process exit (traces may be lost) - Configuring the exporter URL without the path suffix (
/v1/traces)
Source
https://opentelemetry.io/docs/languages/js/getting-started/nodejs/
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.