OpenTelemetry is the current industry-standard framework for generating metrics, logs, and traces from your application code — vendor-neutral, meaning the same instrumentation works with many different backend observability tools.
Why OpenTelemetry Specifically
Before OpenTelemetry, instrumenting applications for observability often meant vendor-specific SDKs, locking you into a particular tool. OpenTelemetry provides one standard instrumentation approach that can export to Jaeger, Prometheus, or many other compatible backends.
Prerequisites
- A running application in your language of choice (examples below use Node.js)
Step 1 — Install OpenTelemetry Packages
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-http
Step 2 — Create an Instrumentation Setup File
nano tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://YOUR_JAEGER_SERVER_IP:4318/v1/traces',
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
Step 3 — Load Instrumentation Before Your Application Code
node -r ./tracing.js app.js
The tracing setup must load before your application's own modules to correctly auto-instrument common libraries (HTTP, database clients, and more).
Step 4 — Verify Traces Are Being Sent
Make a few requests to your application, then check your Jaeger UI (see How to Implement Distributed Tracing with Jaeger) to confirm traces are appearing for your service.
Adding Custom Spans for Specific Business Logic
const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('my-app');
async function processOrder(orderId) {
return tracer.startActiveSpan('process-order', async (span) => {
span.setAttribute('order.id', orderId);
try {
// ... business logic ...
} finally {
span.end();
}
});
}
Auto-instrumentation covers common libraries automatically; custom spans let you add visibility into your own application-specific logic.
Adding Metrics Instrumentation
const { metrics } = require('@opentelemetry/api');
const meter = metrics.getMeter('my-app');
const requestCounter = meter.createCounter('requests_total');
requestCounter.add(1, { route: '/api/orders' });
Instrumenting Other Languages
OpenTelemetry provides SDKs for most major languages (Python, Java, Go, .NET, and others) following the same general pattern — consult the official OpenTelemetry documentation for language-specific setup, since exact API syntax differs.
Exporting to Multiple Backends Simultaneously
OpenTelemetry supports exporting the same instrumentation data to multiple destinations at once (e.g. traces to Jaeger, metrics to Prometheus) — useful if you're using specialized tools for different observability pillars rather than one unified platform.
Common Errors
Auto-instrumentation doesn't capture expected spans — verify the tracing setup file is loaded before your application code (via -r flag or equivalent), not imported after other modules are already loaded.
High overhead from tracing — consider sampling (tracing only a percentage of requests) for high-traffic production services rather than tracing every single request.
Continue Reading
- How to Implement Distributed Tracing with Jaeger
- What Is Observability? Metrics, Logs, and Traces Explained
- How to Set Up Prometheus and Grafana for VPS Monitoring
Browse more articles in Advanced Observability & Incident Management.