Back

OpenTelemetry with Datadog: Which Way Do I Send It?

In the last post I kept brushing up against OpenTelemetry. Every time the backend wasn't dd-trace, the answer was "well, it depends how you're shipping your OTel data," and I waved at a couple of config snippets and moved on.

This is the post where I stop waving.

If you've decided to instrument with OpenTelemetry and you want the data in Datadog, there isn't one path. There are four, and the right one depends on what platform you're on, what processing you need, and which Datadog products you can't live without. The official docs cover each of them well, but they don't really sit you down and explain the trade-offs in one place. So here's my attempt.

Two separate questions

The thing that trips people up is conflating two decisions that are actually independent:

  1. How do you instrument? Pure OpenTelemetry SDK, or a Datadog tracer that speaks the OTel API?
  2. How do you ship it? Straight to the Agent, through a Collector, through DDOT, or direct to the intake?

You can mix and match most of these. Shipping first, because that's where the four paths live.

Path 1: OTLP ingest in the Datadog Agent

If you already run the Datadog Agent, this is the lowest-effort option. The Agent has had an embedded OTLP receiver since version 6.32 / 7.32 (logs since 6.48 / 7.48). You point your OTel exporter at the Agent and it forwards the data into the same pipeline as everything else.

Enable it in datadog.yaml:

otlp_config:
  receiver:
    protocols:
      grpc:
        endpoint: localhost:4317
      http:
        endpoint: localhost:4318

Ports 4317 (gRPC) and 4318 (HTTP) are the OTel defaults. The docs' own examples bind to 0.0.0.0, but they suggest you use localhost unless you actually need to receive from off-box, which is the safer default.

The catch: this is a receiver, not a full Collector. You don't get the OpenTelemetry processor pipeline, so things like tail-based sampling or heavy attribute transformation aren't on the table here. And the supported topology is an ingesting Agent on every host that produces OTel data, not a forwarding tier.

Reach for this when: you're not on Kubernetes or Linux, or you just want OTel data flowing with minimal moving parts and don't need Collector-grade processing.

Path 2: A standalone OpenTelemetry Collector

This is the vendor-neutral route. Run an upstream Collector (the otelcol-contrib distribution, which bundles the datadog exporter) and forward to Datadog:

exporters:
  datadog:
    api:
      site: datadoghq.com
      key: ${env:DD_API_KEY}

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [datadog]

What you gain over Agent OTLP ingest is the full processor pipeline (tail-based sampling, transforms, the lot) and the comfort of running a community distribution you could repoint at another vendor tomorrow.

What you lose is everything that depends on the Datadog Agent being present. With a pure OSS Collector and no Agent, a long list of products is simply unavailable: Database Monitoring, Cloud Network Monitoring, Live Processes, Universal Service Monitoring, App & API Protection, Continuous Profiler, RUM correlation, Source Code Integration. If none of those matter to you, fine. If you're not sure, that list is worth reading twice before you commit.

Reach for this when: you're already invested in upstream Collector distributions, or you need processing the Agent receiver can't do, and you can live without the Agent-tied products.

Path 3: DDOT, the Datadog Distribution of the OTel Collector

This is the newer option, and it's the one Datadog now leads with. DDOT is an actual OpenTelemetry Collector built into the Datadog Agent. The pitch is that you stop choosing between "Collector pipelines" and "Agent features" and get both in one process.

It's GA on Kubernetes; Linux bare-metal/VM is still in preview at the time of writing. Agent v7.65 first introduced it, though the current Kubernetes DaemonSet image wants v7.67 or later.

On Kubernetes via Helm, it's essentially one flag:

datadog:
  otelCollector:
    enabled: true
    ports:
      - containerPort: "4317"
        hostPort: "4317"
        name: otel-grpc
      - containerPort: "4318"
        hostPort: "4318"
        name: otel-http

Out of the box it bundles a sensible set of components: receivers (otlp, filelog, prometheus…), processors (batch, k8sattributes…), exporters (datadog, otlp…), connectors and extensions. If the defaults don't cover you, you can build a custom distribution with additional OTel-compatible components.

The reason this matters: you get the full Collector pipeline and the Agent goodies. That means Fleet Automation for managing the fleet remotely, Datadog's full integration catalogue, live container monitoring, the Kubernetes Explorer, and automatic tag enrichment. That combination is exactly what the standalone Collector makes you give up.

Reach for this when: you're on Kubernetes (or on a Linux host and happy to run a preview), you want OTel pipelines, and you don't want to surrender Agent-side capabilities to get them. For most new Kubernetes deployments this is the path I'd start from.

Path 4: Direct OTLP ingest (no intermediary)

There's also a preview path that sends OTLP straight to the Datadog intake with no Agent or Collector in between. It's handy for serverless or constrained environments where you can't run a collection tier. One sharp edge to know up front: the direct intake accepts delta temporality metrics only and rejects cumulative. More on temporality below, because it bites on the other paths too, just less fatally.

Now the instrumentation question

Shipping aside, how you instrument changes what you can do.

The pure OpenTelemetry SDK is fully vendor-neutral. You instrument against the OTel SDK, export OTLP, and you're not tied to any Datadog library. The cost is that Datadog's proprietary products (Continuous Profiler, App & API Protection, RUM correlation, ingestion-rule sampling) are built around the Datadog tracer and aren't available from a pure OTel SDK.

The bit people miss is that dd-trace implements the OpenTelemetry API itself. You can write your instrumentation against standard OTel interfaces and run the Datadog tracer underneath, without installing the official OTel SDK at all. You enable it per signal: DD_TRACE_OTEL_ENABLED for traces (defaults to false, except Java where it's true), plus the metrics and logs equivalents.

One important warning: for supported languages, don't install both the Datadog tracer and the OTel SDK + OTLP exporter. Running both leads to runtime conflicts and duplicate data. Pick one.

The trade-off is the one you'd expect. OTel-API-on-dd-trace gets you access to more Datadog features than the OTel SDK alone. Pure OTel SDK keeps you portable. If vendor neutrality is the whole reason you're doing this, the pure SDK is the honest choice. If you want OTel-standard instrumentation and Datadog's deeper features, the OTel API on dd-trace is a nice middle ground.

The gotchas that actually cost you an afternoon

A few things that aren't obvious until they bite.

Unified service tagging

With a pure OTel SDK, the DD_SERVICE / DD_ENV / DD_VERSION environment variables you're used to don't work (DDOT does understand them; this gotcha is specific to the vanilla OTel SDK). You set OTel resource attributes instead:

OTEL_RESOURCE_ATTRIBUTES=service.name=checkout,deployment.environment.name=prod,service.version=1.4.2

Datadog maps service.nameservice, service.versionversion, and deployment.environment.nameenv. Note that last one: the old deployment.environment attribute was deprecated in semantic conventions v1.27.0 in favour of deployment.environment.name, and the new form needs Agent 7.58+ and Datadog Exporter v0.110+. And don't set both the DD_* and OTEL_* forms for the same concept, or you'll get duplicate tag values.

Metric temporality

OpenTelemetry SDKs default to cumulative temporality. Datadog works best with delta. If you send cumulative, the pipeline has to diff consecutive points to recover the rate, which makes it stateful (every point of a series has to land on the same Agent or Collector), can drop the first point of each series, and can't recover min/max for cumulative histograms. Set the SDK preference where you can:

OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=Delta

Language support for that varies, and the Collector's cumulativetodelta processor can convert as a fallback, though, like delta conversion in general, it needs every point of a series to reach the same collector instance. And as noted, the direct-intake path rejects cumulative outright.

Feature gaps are real, not theoretical

Datadog publishes a compatibility matrix comparing the setups (Datadog SDK + DDOT, OTel SDK + DDOT, OTel SDK + OSS Collector, direct OTLP). It's the single most useful page to read before you pick a stack, because it tells you in a grid exactly which products you forfeit on each path. Continuous Profiler, AAP and RUM correlation all want the Datadog SDK. Data Streams Monitoring simply has no OTel equivalent.

So which one?

If I had to compress all of the above into a rule of thumb:

  • On Kubernetes, starting fresh: DDOT, instrumented with the Datadog tracer's OTel API. You get OTel-standard instrumentation, full Collector pipelines, and you keep the Agent features. This is Datadog's recommended path and, for most people, the right default.
  • Committed to vendor-neutral OSS, need heavy processing: standalone Collector with the datadog exporter, pure OTel SDK. Eyes open about the products you're giving up.
  • Not on Kubernetes/Linux, or you want minimal fuss: Agent OTLP ingest.
  • Serverless or no room for a collection tier: direct OTLP intake (delta metrics only).

The honest summary is that OpenTelemetry and Datadog aren't an either/or any more, and haven't been for a while. The interesting decisions are no longer "OTel or Datadog"; they're "which collection topology" and "how much vendor neutrality do I actually want, given what it costs me." DDOT exists precisely because most people wanted to stop choosing.

For SEs, this is a better conversation to have than the old one. A prospect who's standardised on OpenTelemetry isn't a lost cause to be argued out of it. They're someone you can meet exactly where they are, OTLP and all, and then show what the Datadog-side features add on top. That's a much easier story to tell.

The starting point for all of this is Datadog's OpenTelemetry docs, and the compatibility matrix is the page I'd bookmark.