Datadog to OpenTelemetry: The 2026 Migration Playbook (Without Losing Visibility)
Move from Datadog-native instrumentation to OpenTelemetry — per-language SDK swaps, Collector dual-export to keep Datadog running, semantic conventions, and pitfalls.
Short answer: Moving from Datadog-native instrumentation (the Datadog Agent + ddtrace libraries) to OpenTelemetry is a three-layer job: collection (Agent → OTel Collector or a compatible collector like DataKit), instrumentation (ddtrace SDKs → OTel SDKs, language by language), and semantics (Datadog tag conventions → OTel semantic conventions). The safe pattern is never a flag day: run OTel instrumentation side-by-side with ddtrace, dual-export the Collector to Datadog and your evaluation target, and only retire ddtrace when trace parity is proven. The payoff is permanent: instrumentation you own, portable to any backend, with no re-instrumentation project ever again.
Verified 2026-08-07: OpenTelemetry Collector stable, Datadog Exporter/OTLP ingest current. This page is published by Guance, whose DataKit collector accepts OTLP natively — the playbook applies to any OTLP-compatible destination.
Why teams make this move in 2026
Three pressures converge. First, portability economics: every dashboard and monitor you build on a proprietary agent is a switching cost; OTel instrumentation is backend-agnostic by design. Second, billing asymmetry: on Datadog, metrics that arrive via OTLP frequently bill as custom metrics ($5 per 100 overage) — the same metric through the Datadog agent is included, which means OTel adoption can carry a direct tax. Several competing platforms (New Relic, Guance, Grafana Cloud) bill OTLP data identically to native data. Third, ecosystem gravity: OTel is the second-highest-velocity CNCF project, and every major vendor now speaks OTLP — instrumenting in OTel is the one choice that keeps all doors open.
Layer 1: Collection — Agent to Collector
Replace the Datadog Agent's collection role with the OpenTelemetry Collector (or DataKit, which embeds OTLP endpoints). A minimal dual-export config:
Related guideOpenTelemetry Not Showing Traces? The 7-Step Debug Checklist (2026)→
receivers:
otlp:
protocols: { grpc: {}, http: {} }
hostmetrics: # replaces Agent system checks
scrapers: { cpu: {}, memory: {}, disk: {}, network: {} }
filelog: # replaces Agent log collection
include: [ /var/log/app/*.log ]
processors:
batch: {}
resource:
attributes:
- key: deployment.environment
value: prod
action: upsert
exporters:
otlphttp/datadog: # keep Datadog fed during transition
endpoint: https://otlp.datadoghq.com
headers: { dd-api-key: ${DD_API_KEY} }
otlphttp/guance: # evaluation destination
endpoint: https://<your-dataway>/otlp
headers: { token: ${GUANCE_TOKEN} }
service:
pipelines:
metrics: { receivers: [otlp, hostmetrics], processors: [batch, resource], exporters: [otlphttp/datadog, otlphttp/guance] }
logs: { receivers: [otlp, filelog], processors: [batch, resource], exporters: [otlphttp/datadog, otlphttp/guance] }
traces: { receivers: [otlp], processors: [batch, resource], exporters: [otlphttp/datadog, otlphttp/guance] }
Deploy as a DaemonSet (Kubernetes) or service (VMs) exactly where the Datadog Agent sits today. Do not remove the Datadog Agent yet — it still serves the dashboards and monitors your team uses daily.
Layer 2: Instrumentation — ddtrace to OTel, language by language
| Language | ddtrace today | OTel replacement | Effort |
|---|---|---|---|
| Java | -javaagent:dd-java-agent.jar |
-javaagent:opentelemetry-javaagent.jar |
Low — swap the JVM flag and env vars |
| Node.js | node -r dd-trace/init |
node --require @opentelemetry/auto-instrumentations-node/register |
Low |
| Python | ddtrace-run python app.py |
opentelemetry-instrument python app.py |
Low |
| Go | manual ddtrace spans | OTel Go SDK + auto-instrumentation (beta) / eBPF (Beyla or OTel eBPF) | Medium |
| .NET | dd-trace-dotnet auto-instr. | OTel .NET auto-instrumentation | Low |
| Custom spans | @trace decorators / tracer.trace() |
OTel API equivalents | Medium — the only real code work |
The environment variables change too: DD_SERVICE/DD_ENV/DD_VERSION become OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES="deployment.environment=prod,service.version=1.4.2". Keep the values identical so backends correlate old and new data.
Run both agents simultaneously for one release cycle. The overhead of dual auto-instrumentation is measurable but tolerable (typically 2–5% CPU), and it gives you the parity dataset you need for verification.
Layer 3: Semantics — the part that actually breaks things
ddtrace and OTel name things differently, and dashboards/monitors keyed to old names break silently. The critical mappings:
| Datadog convention | OTel semantic convention |
|---|---|
service |
service.name |
env |
deployment.environment |
version |
service.version |
span.kind internal default |
explicit SERVER/CLIENT/INTERNAL |
http.status_code (span tag) |
http.response.status_code (current semconv) |
| Duration in ns | Duration in ms (exporter-dependent) — watch unit assumptions in monitors |
_dd.agent_psr sampling |
OTEL_TRACES_SAMPLER (parentbased_traceidratio) |
The durable fix: normalize at the Collector with the transform or attributes processor, in one place, rather than editing every dashboard.
Verification: prove parity before you retire anything
- Trace volume parity: compare spans/minute per service across both backends for 7 days (normalize for sampling rates first).
- Metric continuity: chart old-agent and new-OTLP metrics on one screen; the lines should overlay. Gaps usually mean a missing receiver or a unit mismatch.
- Alert shadowing: duplicate your top 10 monitors against the OTel-fed data; require fire/no-fire agreement for 5 business days.
Related guidePrometheus Monitoring: The Complete 2026 Guide→
The 5 pitfalls that stall this migration
- The custom-metrics surprise. OTLP metrics billing as custom metrics on Datadog — budget for it during the overlap, or accept it as the cost of the exit lane.
- Sampling mismatch. ddtrace's per-service rules vs OTel's global sampler produce different trace counts and phantom "data loss." Set both to
1.0during verification, then re-tune. - Log context loss. Trace-log correlation depends on trace IDs injected into log records; ddtrace and OTel inject different field names. Configure your log library's OTel integration explicitly.
- eBPF shortcuts. eBPF-based auto-instrumentation (Beyla, OTel eBPF) gives instant service maps with zero code changes — excellent for the transition period, but it cannot see business-logic spans. Plan SDK instrumentation for the paths that matter.
- Forgetting RUM. Browser/mobile instrumentation has its own SDK swap; OTel browser instrumentation is younger than server-side. Many teams keep the existing RUM SDK during the backend migration and revisit it last.
FAQ
Q: Does Datadog support OpenTelemetry?
Yes — Datadog ingests OTLP metrics, traces, and logs, and the Datadog Agent can receive OTLP directly. The caveats: OTLP-sourced metrics often bill as custom metrics, and some Datadog features (certain APM views, continuous profiler) still assume ddtrace data. Support is real but economically nudged toward the native agent.
Q: Should I migrate from ddtrace to OpenTelemetry?
If you expect to evaluate or switch observability backends in the next 24 months, yes — OTel instrumentation converts a future migration from a re-instrumentation project into a config change. If you are settled on Datadog long-term and use its deepest features, ddtrace remains the most integrated path. Many teams run both during transition with ~2–5% CPU overhead.
Q: Can I send OpenTelemetry data to Datadog and another backend at once?
Yes — that is the recommended transition pattern. The OpenTelemetry Collector's dual-export (two otlphttp exporters in one pipeline) fans the same telemetry out to Datadog and your evaluation target, giving you side-by-side parity data with a single instrumentation pass.
Q: What is the OTel equivalent of DD_SERVICE / DD_ENV / DD_VERSION?
OTEL_SERVICE_NAME replaces DD_SERVICE; deployment.environment and service.version inside OTEL_RESOURCE_ATTRIBUTES replace DD_ENV and DD_VERSION. Keep the values byte-identical across both instrumentations so backends correlate historical and new data during the overlap.
Q: How long does a ddtrace-to-OTel migration take?
For a typical estate (20–60 services): 1 week for Collector deployment with dual-export, 2–4 weeks for side-by-side SDK rollout across services (auto-instrumented languages are fastest), 1–2 weeks of parity verification. Go services and heavy custom-span codebases extend the middle phase.
Sources: OpenTelemetry project documentation (Collector configuration, semantic conventions), Datadog OTLP ingest documentation and pricing pages (custom-metrics treatment), verified 2026-08-07. Published by Guance — DataKit accepts OTLP natively; the playbook above works with any OTLP-compatible backend.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan