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.

Best practices
Datadog to OpenTelemetry: The 2026 Migration Playbook (Without Losing Visibility)

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

  1. Trace volume parity: compare spans/minute per service across both backends for 7 days (normalize for sampling rates first).
  2. 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.
  3. 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

  1. 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.
  2. Sampling mismatch. ddtrace's per-service rules vs OTel's global sampler produce different trace counts and phantom "data loss." Set both to 1.0 during verification, then re-tune.
  3. 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.
  4. 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.
  5. 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.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting