---
title: Set Up the OpenTelemetry Collector
description: Send OpenTelemetry data to Datadog using the OpenTelemetry Collector and OTLP
breadcrumbs: >-
  Docs > OpenTelemetry in Datadog > Send OpenTelemetry Data to Datadog > Set Up
  the OpenTelemetry Collector
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# Set Up the OpenTelemetry Collector

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Overview{% #overview %}

Send traces, metrics, and logs to Datadog using the OpenTelemetry Collector. The configurations on this page are tested with the OpenTelemetry Collector Contrib distribution v0.154.0 and use an OTLP-based telemetry pipeline with the following key components:

- **OTLP HTTP exporter**: Sends telemetry to Datadog's OTLP intake endpoints.
- **Span metrics connector**: Generates RED (Rate, Error, Duration) metrics from trace data to power APM features such as the Service Catalog and Service Page.
- **Resource detection processor**: Detects host and cloud resource attributes, which Datadog uses for hostname resolution and tagging.
- **Datadog extension**: Reports the Collector's configuration to Datadog for Fleet Automation. It does not export telemetry data.

This is the recommended setup for a Collector you manage yourself. If you want a Collector distribution that Datadog maintains and supports, use the [Datadog Distribution of OTel Collector (DDOT)](https://docs.datadoghq.com/opentelemetry/setup/ddot_collector/install.md) instead.

{% image
   source="https://docs.dd-static.net/images/opentelemetry/setup/oss-collector.87b23183d15b59aacf4be6dff082d82f.png?auto=format&fit=max&w=850 1x, https://docs.dd-static.net/images/opentelemetry/setup/oss-collector.87b23183d15b59aacf4be6dff082d82f.png?auto=format&fit=max&w=850&dpr=2 2x"
   alt="An OpenTelemetry SDK sends OTLP data to an OpenTelemetry Collector, which exports it to Datadog over OTLP HTTP." /%}

The configurations on this page use the [agent deployment pattern](https://opentelemetry.io/docs/collector/deploy/agent/): one Collector runs on each host or Kubernetes node and receives telemetry from workloads on that host or node. For a gateway deployment, see the OpenTelemetry [gateway deployment pattern](https://opentelemetry.io/docs/collector/deploy/gateway/). Stateful processing such as tail-based sampling in a multi-Collector environment requires a gateway architecture that routes all spans for a trace to the same Collector.

{% alert level="info" %}
Already using the Datadog Exporter and Datadog Connector? See [Configure the Datadog Exporter and Connector](https://docs.datadoghq.com/opentelemetry/setup/collector_exporter/datadog_exporter.md).
{% /alert %}

## Prerequisites{% #prerequisites %}

This setup supports bare metal, VMs, Docker, and Kubernetes. Supported managed Kubernetes distributions include Amazon EKS (including Auto Mode), Google GKE (Standard and Autopilot), and Azure AKS (including Automatic).

This setup does not support serverless or task-based container runtimes such as ECS Fargate, EKS Fargate, or AWS Lambda. For supported Datadog features, see the [feature compatibility table](https://docs.datadoghq.com/opentelemetry/compatibility.md) under **OTel SDK + Upstream OpenTelemetry Collector**.

- [OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib) v0.154.0 or later
- A [Datadog API key](https://docs.datadoghq.com/account_management/api-app-keys.md)
- Your [Datadog site](https://docs.datadoghq.com/getting_started/site.md) (for example, `datadoghq.com` or `datadoghq.eu`)

## Install and configure{% #install-and-configure %}

### 1. Download the OpenTelemetry Collector

Download the latest release of the OpenTelemetry Collector Contrib distribution from the [releases page](https://github.com/open-telemetry/opentelemetry-collector-releases/releases/latest).

### 2. Configure and deploy the Collector

Select the tab for your environment.

{% tab title="Host" %}
For an uncontainerized Collector running directly on a host (bare metal or VM), create a file named `collector.yaml` with this configuration.

Set the `DD_API_KEY` and `DD_SITE` environment variables before starting the Collector.

```yaml
receivers:
  # Receive telemetry from OpenTelemetry-instrumented applications
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  # Collect host system metrics (CPU, memory, disk, network); populates the Infrastructure List
  host_metrics:
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization:
            enabled: true
          system.cpu.physical.count:
            enabled: true
          system.cpu.logical.count:
            enabled: true
          system.cpu.frequency:
            enabled: true
      memory:
        metrics:
          system.memory.limit:
            enabled: true
      paging:
        metrics:
          system.paging.utilization:
            enabled: true
          system.paging.usage:
            enabled: true
      disk: {}
      filesystem:
        metrics:
          system.filesystem.utilization:
            enabled: true
      load: {}
      network: {}
      processes: {}

processors:
  # Detect host and cloud resource attributes for hostname resolution and tagging
  resource_detection:
    detectors: [env, system]
    timeout: 2s
    override: true # Disable if incoming attributes (especially host.name) are verified correct
  # Convert cumulative metrics to delta temporality for Datadog
  cumulativetodelta: {}

connectors:
  # Separate trace processing from sampling so span metrics are computed on all traces
  forward/traces_sample: {}
  # Generate RED (Rate, Error, Duration) metrics from traces for APM
  span_metrics:
    aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA
    add_resource_attributes: true
    histogram:
      exponential: {}
      unit: s
    dimensions:
      ## Unified Service Tagging
      - name: deployment.environment.name
      - name: service.version
      - name: http.response.status_code
      ## Container tags
      - name: container.id
      ## Host name inference
      - name: aws.ecs.launchtype
      - name: aws.ecs.task.arn
      - name: cloud.provider
      - name: cloud.account.id
      - name: host.id
      - name: host.name
      - name: k8s.node.name
      - name: k8s.cluster.name
      - name: azure.resourcegroup.name
      ## Peer service inference
      - name: aws.s3.bucket
      - name: db.namespace
      - name: messaging.destination.name
      - name: messaging.system
      - name: server.address
      ## Operation name inference
      - name: operation.name
      - name: http.request.method
      - name: http.method
      - name: db.system
      - name: messaging.operation
      - name: rpc.system
      - name: rpc.service
      - name: faas.invoked_provider
      - name: faas.invoked_name
      - name: faas.trigger
      - name: graphql.operation.type
      - name: network.protocol.name
      ## Resource name inference
      - name: resource.name
      - name: http.route
      - name: messaging.destination
      - name: rpc.method
      - name: graphql.operation.name
      - name: db.statement
      - name: db.query.text

exporters:
  # Send telemetry to Datadog's OTLP intake endpoints
  otlp_http:
    endpoint: https://otlp.${env:DD_SITE}
    headers:
      dd-api-key: ${env:DD_API_KEY}
      # Map resource attributes and instrumentation scope metadata to Datadog metric tags
      dd-otel-metric-config: >-
        {
        "resource_attributes_as_tags": true,
        "instrumentation_scope_metadata_as_tags": true
        }
    compression: zstd
    compression_params:
      level: 3 # Must be set explicitly for zstd; the default uses the lowest compression level
    sending_queue:
      batch:
        sizer: bytes
        min_size: 2097152 # Start flushing batches at 2MiB (2 * 1024 * 1024)
        max_size: 4194304 # Split large batches at 4MiB (4 * 1024 * 1024)

extensions:
  # Report Collector configuration to Datadog for Fleet Automation
  datadog:
    api:
      site: ${env:DD_SITE}
      key: ${env:DD_API_KEY}
    deployment_type: daemonset

service:
  extensions:
    - datadog
  pipelines:
    logs:
      receivers: [otlp]
      processors: [resource_detection]
      exporters: [otlp_http]
    metrics:
      receivers: [otlp, host_metrics]
      processors: [resource_detection, cumulativetodelta]
      exporters: [otlp_http]
    traces:
      receivers: [otlp]
      processors: [resource_detection]
      exporters: [forward/traces_sample, span_metrics]
    traces/sample:
      receivers: [forward/traces_sample]
      # Add sampling processors here (for example, tail_sampling) before exporting traces
      exporters: [otlp_http]
    metrics/span_metrics:
      receivers: [span_metrics]
      exporters: [otlp_http]
  telemetry:
    # Route Collector self-monitoring metrics through its own pipelines
    metrics:
      readers:
        - periodic:
            exporter:
              otlp:
                protocol: http/protobuf
                endpoint: http://localhost:4318
```

For cloud-specific environments, add the appropriate resource detection detector:

- **Amazon EC2**: `detectors: [ec2, env, system]`
- **Google Cloud**: `detectors: [gcp, env, system]`
- **Azure**: `detectors: [azure, env, system]`

See the [full configuration files](https://github.com/DataDog/opentelemetry-examples/tree/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector) for an optional config to gather additional metadata about the system.

Run the Collector:

```shell
DD_SITE=<span class="js-region-param region-param" data-region-param="dd_site"></span> DD_API_KEY=<YOUR_API_KEY> \
  otelcol-contrib --config collector.yaml
```

{% /tab %}

{% tab title="Docker" %}
For a containerized Collector, create a file named `collector.yaml` with this configuration. The `host_metrics` receiver requires mounting the host filesystem at `/hostfs`.

Set the following environment variables before starting the Collector:

- `DD_API_KEY` and `DD_SITE`
- `OTEL_RESOURCE_ATTRIBUTES`: The Collector cannot detect host information from inside a container, so provide it here (for example, `host.name=<YOUR_HOST_NAME>`).

```yaml
receivers:
  # Receive telemetry from OpenTelemetry-instrumented applications
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  # Collect host system metrics (CPU, memory, disk, network); populates the Infrastructure List
  # root_path maps to the host filesystem mounted at /hostfs
  host_metrics:
    root_path: /hostfs
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization:
            enabled: true
          system.cpu.physical.count:
            enabled: true
          system.cpu.logical.count:
            enabled: true
          system.cpu.frequency:
            enabled: true
      memory:
        metrics:
          system.memory.limit:
            enabled: true
      paging:
        metrics:
          system.paging.utilization:
            enabled: true
          system.paging.usage:
            enabled: true
      disk: {}
      filesystem:
        metrics:
          system.filesystem.utilization:
            enabled: true
      load: {}
      network: {}
      processes: {}

processors:
  # Detect host and cloud resource attributes for hostname resolution and tagging
  resource_detection:
    detectors: [env]
    timeout: 2s
    override: true # Disable if incoming attributes (especially host.name) are verified correct
  # Convert cumulative metrics to delta temporality for Datadog
  cumulativetodelta: {}

connectors:
  # Separate trace processing from sampling so span metrics are computed on all traces
  forward/traces_sample: {}
  # Generate RED (Rate, Error, Duration) metrics from traces for APM
  span_metrics:
    aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA
    add_resource_attributes: true
    histogram:
      exponential: {}
      unit: s
    dimensions:
      ## Unified Service Tagging
      - name: deployment.environment.name
      - name: service.version
      - name: http.response.status_code
      ## Container tags
      - name: container.id
      ## Host name inference
      - name: aws.ecs.launchtype
      - name: aws.ecs.task.arn
      - name: cloud.provider
      - name: cloud.account.id
      - name: host.id
      - name: host.name
      - name: k8s.node.name
      - name: k8s.cluster.name
      - name: azure.resourcegroup.name
      ## Peer service inference
      - name: aws.s3.bucket
      - name: db.namespace
      - name: messaging.destination.name
      - name: messaging.system
      - name: server.address
      ## Operation name inference
      - name: operation.name
      - name: http.request.method
      - name: http.method
      - name: db.system
      - name: messaging.operation
      - name: rpc.system
      - name: rpc.service
      - name: faas.invoked_provider
      - name: faas.invoked_name
      - name: faas.trigger
      - name: graphql.operation.type
      - name: network.protocol.name
      ## Resource name inference
      - name: resource.name
      - name: http.route
      - name: messaging.destination
      - name: rpc.method
      - name: graphql.operation.name
      - name: db.statement
      - name: db.query.text

exporters:
  # Send telemetry to Datadog's OTLP intake endpoints
  otlp_http:
    endpoint: https://otlp.${env:DD_SITE}
    headers:
      dd-api-key: ${env:DD_API_KEY}
      # Map resource attributes and instrumentation scope metadata to Datadog metric tags
      dd-otel-metric-config: >-
        {
        "resource_attributes_as_tags": true,
        "instrumentation_scope_metadata_as_tags": true
        }
    compression: zstd
    compression_params:
      level: 3 # Must be set explicitly for zstd; the default uses the lowest compression level
    sending_queue:
      batch:
        sizer: bytes
        min_size: 2097152 # Start flushing batches at 2MiB (2 * 1024 * 1024)
        max_size: 4194304 # Split large batches at 4MiB (4 * 1024 * 1024)

extensions:
  # Report Collector configuration to Datadog for Fleet Automation
  datadog:
    api:
      site: ${env:DD_SITE}
      key: ${env:DD_API_KEY}
    deployment_type: daemonset

service:
  extensions:
    - datadog
  pipelines:
    logs:
      receivers: [otlp]
      processors: [resource_detection]
      exporters: [otlp_http]
    metrics:
      receivers: [otlp, host_metrics]
      processors: [resource_detection, cumulativetodelta]
      exporters: [otlp_http]
    traces:
      receivers: [otlp]
      processors: [resource_detection]
      exporters: [forward/traces_sample, span_metrics]
    traces/sample:
      receivers: [forward/traces_sample]
      # Add sampling processors here (for example, tail_sampling) before exporting traces
      exporters: [otlp_http]
    metrics/span_metrics:
      receivers: [span_metrics]
      exporters: [otlp_http]
  telemetry:
    # Route Collector self-monitoring metrics through its own pipelines
    metrics:
      readers:
        - periodic:
            exporter:
              otlp:
                protocol: http/protobuf
                endpoint: http://localhost:4318
```

Create a Docker network for the Collector and your application containers to share, or use an existing one:

```shell
docker network create otel
```

Run the Collector with the host filesystem mounted, attached to that network:

```shell
docker run \
    --name otelcol \
    --network otel \
    -p 4317:4317 \
    -p 4318:4318 \
    -e DD_API_KEY \
    -e DD_SITE \
    -e OTEL_RESOURCE_ATTRIBUTES \
    -v /:/hostfs:ro \
    -v $(pwd)/collector.yaml:/etc/otelcol-contrib/config.yaml \
    otel/opentelemetry-collector-contrib:0.154.0 \
    --config /etc/otelcol-contrib/config.yaml
```

{% /tab %}

{% tab title="Kubernetes" %}
Use the [official OpenTelemetry Collector Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/opentelemetry-collector-0.147.1/charts/opentelemetry-collector) to deploy the Collector as a DaemonSet in Kubernetes. The example values files are tested with chart v0.147.1, pin the Collector to v0.154.0, and set up the required mounts, environment variables, RBAC resources, and port exposure.

1. Create a Kubernetes secret with your Datadog API key:

   ```shell
   kubectl create secret generic datadog-secrets --from-literal=api-key='<YOUR_API_KEY>'
   ```

1. Add the OpenTelemetry Helm repository:

   ```shell
   helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
   ```

1. Download the example values file for your environment and save it as `values.yaml`. If your Datadog site is not `datadoghq.com`, update the `DD_SITE` value in `values.yaml` before installing.

| Environment            | Values file                                                                                                                                                                                                       |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Kubernetes (non-cloud) | [`daemonset.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset.yaml)                             |
| Amazon EKS             | [`daemonset-eks.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-eks.yaml)                     |
| Amazon EKS Auto Mode   | [`daemonset-eks-auto.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-eks-auto.yaml)           |
| Google GKE             | [`daemonset-gke.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-gke.yaml)                     |
| Google GKE Autopilot   | [`daemonset-gke-autopilot.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-gke-autopilot.yaml) |
| Azure AKS              | [`daemonset-aks.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-aks.yaml)                     |
| Azure AKS Automatic    | [`daemonset-aks-automatic.yaml`](https://github.com/DataDog/opentelemetry-examples/blob/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector/helm-values/daemonset-aks-automatic.yaml) |

On Amazon EKS, the values files cannot configure the required AWS-side settings. Apply the following outside of Helm:

   - **Amazon EKS**: The `ec2` and `eks` detectors need access to the IMDS endpoint from inside a container. Set the IMDS token hop limit to 2 in your node launch template or in your account settings.
   - **Amazon EKS Auto Mode**: The `eks` detector requires a Pod Identity association that assigns the Collector an IAM role with the `EC2:DescribeInstances` permission.

1. Install the Collector:

   ```shell
   helm install otelcol open-telemetry/opentelemetry-collector --version 0.147.1 --values values.yaml
   ```

{% /tab %}

{% tab title="Kubernetes manifest reference" %}
This tab is a configuration reference for users who maintain their own Kubernetes manifests. For an executable installation that includes the required pod specification, mounts, environment variables, RBAC resources, and port exposure, use the **Kubernetes** tab.

The configuration runs the Collector as a DaemonSet in a non-cloud environment. It includes the `k8s_attributes` processor for enriching telemetry with Kubernetes metadata and the `kubelet_stats` receiver for node, pod, container, and volume metrics. On a managed Kubernetes distribution, apply the changes described in Managed Kubernetes distributions after the configuration.

Set the following environment variables in the Collector pod spec, using the Kubernetes downward API where noted:

- `DD_API_KEY` and `DD_SITE`
- `K8S_NODE_NAME`: The name of the Kubernetes node, used by the `kubelet_stats` receiver. Set it from the `spec.nodeName` field.
- `MY_POD_IP`: The pod IP, used by the `health_check` extension. Set it from the `status.podIP` field.
- `OTEL_RESOURCE_ATTRIBUTES`: The Collector cannot determine the host name from inside a container, so provide host information here (for example, `k8s.node.name=$(K8S_NODE_NAME)`). The `$(VAR)` syntax is expanded by Kubernetes, so set this in the pod spec rather than in a shell.

Mount the host filesystem at `/hostfs` so the `host_metrics` receiver can collect host metrics.

```yaml
receivers:
  # Receive telemetry from OpenTelemetry-instrumented applications
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  # Collect host system metrics (CPU, memory, disk, network); populates the Infrastructure List
  # root_path maps to the host filesystem mounted at /hostfs
  host_metrics:
    root_path: /hostfs
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization:
            enabled: true
          system.cpu.physical.count:
            enabled: true
          system.cpu.logical.count:
            enabled: true
          system.cpu.frequency:
            enabled: true
      memory:
        metrics:
          system.memory.limit:
            enabled: true
      paging:
        metrics:
          system.paging.utilization:
            enabled: true
          system.paging.usage:
            enabled: true
      disk: {}
      filesystem:
        metrics:
          system.filesystem.utilization:
            enabled: true
      load: {}
      network: {}
      processes: {}
  # Collect node, pod, container, and volume metrics from the kubelet
  kubelet_stats:
    collection_interval: 15s
    auth_type: "serviceAccount"
    endpoint: "${env:K8S_NODE_NAME}:10250"
    node: "${env:K8S_NODE_NAME}"
    insecure_skip_verify: true
    metric_groups:
      - node
      - pod
      - container
      - volume

processors:
  # Detect host and cloud resource attributes for hostname resolution and tagging
  resource_detection:
    detectors: [env, system]
    timeout: 2s
    override: true # Disable if incoming attributes (especially host.name) are verified correct
    system:
      resource_attributes:
        host.name:
          enabled: false # Containers report inaccurate host names
  # Convert cumulative metrics to delta temporality for Datadog
  cumulativetodelta: {}
  # Convert selected delta metrics to rates
  deltatorate:
    metrics:
      - k8s.pod.network.io
      - k8s.pod.network.errors
  # Enrich telemetry with Kubernetes pod and container metadata
  k8s_attributes:
    extract:
      otel_annotations: true
      metadata:
        - k8s.node.name
        - k8s.namespace.name
        - service.namespace
        - service.name
        - service.version
        - service.instance.id
        - k8s.deployment.name
        - k8s.replicaset.name
        - k8s.daemonset.name
        - k8s.statefulset.name
        - k8s.cronjob.name
        - k8s.job.name
        - k8s.pod.uid
        - k8s.pod.name
        - container.id
        - k8s.container.name
        - container.image.name
        - container.image.tag
    pod_association:
      - sources:
          - from: resource_attribute
            name: k8s.pod.uid
      - sources:
          - from: resource_attribute
            name: k8s.pod.ip
      - sources:
          - from: resource_attribute
            name: k8s.pod.name
          - from: resource_attribute
            name: k8s.namespace.name
      - sources:
          - from: connection

connectors:
  # Separate trace processing from sampling so span metrics are computed on all traces
  forward/traces_sample: {}
  # Generate RED (Rate, Error, Duration) metrics from traces for APM
  span_metrics:
    aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA
    add_resource_attributes: true
    histogram:
      exponential: {}
      unit: s
    dimensions:
      ## Unified Service Tagging
      - name: deployment.environment.name
      - name: service.version
      - name: http.response.status_code
      ## Container tags
      - name: container.id
      ## Host name inference
      - name: aws.ecs.launchtype
      - name: aws.ecs.task.arn
      - name: cloud.provider
      - name: cloud.account.id
      - name: host.id
      - name: host.name
      - name: k8s.node.name
      - name: k8s.cluster.name
      - name: azure.resourcegroup.name
      ## Peer service inference
      - name: aws.s3.bucket
      - name: db.namespace
      - name: messaging.destination.name
      - name: messaging.system
      - name: server.address
      ## Operation name inference
      - name: operation.name
      - name: http.request.method
      - name: http.method
      - name: db.system
      - name: messaging.operation
      - name: rpc.system
      - name: rpc.service
      - name: faas.invoked_provider
      - name: faas.invoked_name
      - name: faas.trigger
      - name: graphql.operation.type
      - name: network.protocol.name
      ## Resource name inference
      - name: resource.name
      - name: http.route
      - name: messaging.destination
      - name: rpc.method
      - name: graphql.operation.name
      - name: db.statement
      - name: db.query.text

exporters:
  # Send telemetry to Datadog's OTLP intake endpoints
  otlp_http:
    endpoint: https://otlp.${env:DD_SITE}
    headers:
      dd-api-key: ${env:DD_API_KEY}
      # Map resource attributes and instrumentation scope metadata to Datadog metric tags
      dd-otel-metric-config: >-
        {
        "resource_attributes_as_tags": true,
        "instrumentation_scope_metadata_as_tags": true
        }
    compression: zstd
    compression_params:
      level: 3 # Must be set explicitly for zstd; the default uses the lowest compression level
    sending_queue:
      batch:
        sizer: bytes
        min_size: 2097152 # Start flushing batches at 2MiB (2 * 1024 * 1024)
        max_size: 4194304 # Split large batches at 4MiB (4 * 1024 * 1024)

extensions:
  # Required for Kubernetes liveness/readiness probes
  health_check:
    endpoint: ${env:MY_POD_IP}:13133
  # Report Collector configuration to Datadog for Fleet Automation
  datadog:
    api:
      site: ${env:DD_SITE}
      key: ${env:DD_API_KEY}
    deployment_type: daemonset

service:
  extensions:
    - health_check
    - datadog
  pipelines:
    logs:
      receivers: [otlp]
      processors: [k8s_attributes, resource_detection]
      exporters: [otlp_http]
    metrics:
      receivers: [otlp, host_metrics, kubelet_stats]
      processors: [k8s_attributes, resource_detection, cumulativetodelta, deltatorate]
      exporters: [otlp_http]
    traces:
      receivers: [otlp]
      processors: [k8s_attributes, resource_detection]
      exporters: [forward/traces_sample, span_metrics]
    traces/sample:
      receivers: [forward/traces_sample]
      # Add sampling processors here (for example, tail_sampling) before exporting traces
      exporters: [otlp_http]
    metrics/span_metrics:
      receivers: [span_metrics]
      exporters: [otlp_http]
  telemetry:
    # Route Collector self-monitoring metrics through its own pipelines
    metrics:
      readers:
        - periodic:
            exporter:
              otlp:
                protocol: http/protobuf
                endpoint: http://localhost:4318
```

This configuration requires a ServiceAccount bound to a ClusterRole that grants `get`, `list`, and `watch` on `pods`, `namespaces`, `nodes`, `nodes/stats`, and `replicasets`. The `k8s_attributes` processor reads pod metadata, and the `kubelet_stats` receiver reads `nodes/stats`. See the [Kubernetes Attributes Processor documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor#role-based-access-control) for RBAC setup instructions, and add `nodes/stats` to the rules it lists.

#### Managed Kubernetes distributions{% #managed-kubernetes-distributions %}

On a managed Kubernetes distribution, replace the `resource_detection` processor in the previous configuration with the variant for your environment. The cloud detectors provide host information, so you do not need to set `OTEL_RESOURCE_ATTRIBUTES`.

##### Amazon EKS{% #amazon-eks %}

```yaml
processors:
  resource_detection:
    detectors: [eks, ec2, env, system]
    timeout: 15s
    override: true
    eks:
      resource_attributes:
        k8s.cluster.name: { enabled: true }
    ec2:
      tags: ['^kubernetes\.io/cluster/.*$']
    system:
      resource_attributes:
        host.name:
          enabled: false
```

The `ec2` and `eks` detectors need access to the IMDS endpoint from inside a container. Set the IMDS token hop limit to 2 in your node launch template or in your account settings. The `timeout` is raised to `15s` to allow for IMDS latency.

##### Amazon EKS Auto Mode{% #amazon-eks-auto-mode %}

```yaml
processors:
  resource_detection:
    detectors: [eks, env, system]
    timeout: 15s
    override: true
    eks:
      resource_attributes:
        k8s.cluster.name: { enabled: true }
        host.id: { enabled: true } # Required for host name inference
        cloud.account.id: { enabled: true }
        cloud.availability_zone: { enabled: true }
        cloud.region: { enabled: true }
        host.image.id: { enabled: true }
        host.type: { enabled: true }
      node_from_env_var: K8S_NODE_NAME
    system:
      resource_attributes:
        host.name:
          enabled: false
```

The `eks` detector requires a Pod Identity association that assigns the Collector an IAM role with the `EC2:DescribeInstances` permission.

##### Google GKE{% #google-gke %}

```yaml
processors:
  resource_detection:
    detectors: [gcp, env, system]
    timeout: 2s
    override: true
    system:
      resource_attributes:
        host.name:
          enabled: false
```

On older GKE versions, the `gcp` detector may not return a host name. If that happens, supply the node name as `host.name` in `OTEL_RESOURCE_ATTRIBUTES`.

##### Azure AKS{% #azure-aks %}

```yaml
processors:
  resource_detection:
    detectors: [aks, azure, env, system]
    timeout: 2s
    override: true
    aks:
      resource_attributes:
        k8s.cluster.name: { enabled: true }
    system:
      resource_attributes:
        host.name:
          enabled: false
```

##### GKE Autopilot and AKS Automatic{% #gke-autopilot-and-aks-automatic %}

These modes do not allow mounting `/hostfs` or using host ports. Use the GKE or AKS `resource_detection` processor, then make these additional changes:

- Remove the `host_metrics` receiver from the `receivers` block and from the `metrics` pipeline. Node, pod, container, and volume metrics still come from the `kubelet_stats` receiver.
- Disable host ports on the Collector and expose it through a node-local Service instead. The GKE Autopilot and AKS Automatic Helm values files apply these changes. Point applications at that Service rather than at the host IP shown in Configure your application.

For the complete configuration files for each environment, see the [`opentelemetry-examples` repository](https://github.com/DataDog/opentelemetry-examples/tree/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector).
{% /tab %}

### 3. Configure your application

Configure your OpenTelemetry-instrumented application to send data to the Collector. Set the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable to point to the Collector:

{% tab title="Host" %}

```shell
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
```

{% /tab %}

{% tab title="Docker" %}
Set the following environment variables in your application container:

```
OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
```

This uses the `--name otelcol` value from the `docker run` command. Run your application container on the same network (`--network otel`). If you use Docker Compose, both containers share a network automatically and you can use the Collector's service name.
{% /tab %}

{% tab title="Kubernetes" %}
For Kubernetes environments where the Helm values enable host ports, configure the endpoint using the host IP:

```yaml
env:
  - name: HOST_IP
    valueFrom:
      fieldRef:
        fieldPath: status.hostIP
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: "http://$(HOST_IP):4318"
  - name: OTEL_EXPORTER_OTLP_PROTOCOL
    value: "http/protobuf"
```

GKE Autopilot and AKS Automatic do not allow host ports. Their example Helm values enable a node-local Service instead. Find the Service name with `kubectl get services`, and configure the endpoint using its Kubernetes DNS name (for example, `http://otelcol-opentelemetry-collector:4318`).
{% /tab %}

Set the `service.name`, `deployment.environment.name`, and `service.version` resource attributes in your application's OpenTelemetry configuration. Datadog maps these to [Unified Service Tagging](https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging.md), which correlates your traces, metrics, and logs.

## Verify the setup{% #verify-the-setup %}

After your application sends telemetry to the Collector, verify that data appears in Datadog:

1. In Datadog, go to APM > Services and confirm that your `service.name` appears.
1. Open APM > Traces and search for your service.
1. Go to Infrastructure > Infrastructure List and confirm that the host running the Collector appears. On GKE Autopilot and AKS Automatic, the example values files omit the `host_metrics` receiver, so hosts do not appear.
1. If you send logs through OTLP, go to Logs Explorer and search for your service name.
1. In [Fleet Automation](https://app.datadoghq.com/fleet), confirm that the Collector and its configuration appear.

## Key components{% #key-components %}

### Span metrics connector{% #span-metrics-connector %}

The `span_metrics` connector generates RED metrics from trace data. These metrics power APM features including the Service Catalog, Service Page, and Resource Page. The connector is configured with dimensions that enable Datadog to compute host tags, peer services, and operation names from your traces.

Each environment-specific configuration in Configure and deploy the Collector includes the complete `span_metrics` connector block. Retain all of its dimensions when adapting the configuration so Datadog can derive the required host tags, peer services, operation names, and resource names.

The [full configuration files](https://github.com/DataDog/opentelemetry-examples/tree/be842bc1447337c32f2d6265612232932a6cdbfd/configurations/opentelemetry-collector) also show how to replace groups of container tag dimensions with glob patterns, such as `- glob: container.**`.

### OTLP HTTP exporter{% #otlp-http-exporter %}

The `otlp_http` exporter sends telemetry data to Datadog's OTLP intake endpoints. Key configuration details:

- **Endpoint**: `https://otlp.<YOUR_DD_SITE>` for traces, logs, and metrics.
- **Compression**: `zstd` is recommended for reduced bandwidth usage. When using `zstd`, set `compression_params.level` explicitly, because the default uses the lowest compression level.
- **Batching**: The `sending_queue.batch` settings begin flushing at 2 MiB and split serialized batches at 4 MiB. If you receive a 413 response, reduce these sizes.

#### `dd-otel-metric-config` header{% #dd-otel-metric-config-header %}

The `dd-otel-metric-config` header is a JSON payload sent with metrics requests that configures how Datadog processes OTLP metrics. Set it in the `headers` section of the `otlp_http` exporter.

| Field                                        | Type    | Default               | Description                                                                                                                                                                                                 |
| -------------------------------------------- | ------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `resource_attributes_as_tags`                | Boolean | `false`               | Propagates OTLP resource attributes as Datadog tags on emitted metrics.                                                                                                                                     |
| `instrumentation_scope_metadata_as_tags`     | Boolean | `false`               | Propagates OTLP instrumentation scope metadata (scope name and version) as tags on emitted metrics.                                                                                                         |
| `trace_metrics.namespace`                    | String  | `traces.span.metrics` | Namespace prefix applied to trace-derived metrics.                                                                                                                                                          |
| `trace_metrics.instrumentation_metrics_calc` | Boolean | `false`               | When `true`, routes supported HTTP instrumentation metrics to power APM trace metrics.                                                                                                                      |
| `raw_instrumentation_metrics_drop`           | Boolean | `false`               | When `true`, drops the raw HTTP instrumentation metrics from the regular metrics intake after routing them for APM trace metrics. Only applies when `trace_metrics.instrumentation_metrics_calc` is `true`. |

Example with instrumentation metrics enabled:

```json
{
  "trace_metrics": {
    "namespace": "myapp.traces",
    "instrumentation_metrics_calc": true
  },
  "raw_instrumentation_metrics_drop": false,
  "resource_attributes_as_tags": true,
  "instrumentation_scope_metadata_as_tags": false
}
```

{% alert level="info" %}
The recommended OpenTelemetry Collector configuration uses the `span_metrics` connector to generate the RED metrics that power APM views. The `trace_metrics.instrumentation_metrics_calc` and `raw_instrumentation_metrics_drop` fields support an alternative configuration for setups that derive APM trace metrics from HTTP instrumentation metrics instead. Do not enable `instrumentation_metrics_calc` alongside the `span_metrics` connector, as this computes trace metrics from both sources.
{% /alert %}

### Trace forward connector{% #trace-forward-connector %}

The `forward/traces_sample` connector splits trace processing into two pipelines. The first pipeline sends every span to the `span_metrics` connector, and the second exports spans to Datadog. Add sampling processors to the second pipeline so that trace metrics are computed from all traces, not only the sampled ones.

### Datadog extension{% #datadog-extension %}

The `datadog` extension reports the Collector's configuration to Datadog for Fleet Automation. It does not export telemetry data. All telemetry flows through the OTLP HTTP exporter. This extension is part of the [OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib) project and handles API key validation and deployment type reporting.

### Cumulative-to-delta processor{% #cumulative-to-delta-processor %}

The `cumulativetodelta` processor converts cumulative metrics to delta temporality, which is [Datadog's recommended configuration](https://docs.datadoghq.com/opentelemetry/guide/otlp_delta_temporality.md) for OpenTelemetry metrics.

### Kubelet stats receiver{% #kubelet-stats-receiver %}

In Kubernetes deployments, the `kubelet_stats` receiver collects node, pod, container, and volume metrics from the kubelet on each node. The `deltatorate` processor converts the pod network metrics it produces to rates.

### Self-monitoring telemetry{% #self-monitoring-telemetry %}

The configuration sends the Collector's own metrics back to its local OTLP receiver (`http://localhost:4318`). This routes the Collector's internal metrics through its own pipelines so they are enriched with resource attributes before being exported to Datadog.

## OTLP intake limits{% #otlp-intake-limits %}

Datadog enforces the following limits when ingesting OTLP data. Data that exceeds a limit is rejected or dropped as noted.

{% dl %}

{% dt %}
**Payload size**
{% /dt %}

{% dd %}
Each intake endpoint enforces a maximum payload size per request. Requests above the limit are rejected with an `HTTP 413 Request Entity Too Large` response. If you receive a 413, reduce the batch size or flush more frequently so each request stays under the limit. For the payload size limit of each endpoint, see [Intake limits](https://docs.datadoghq.com/opentelemetry/setup/otlp_ingest.md#intake-limits).
{% /dd %}

{% dt %}
**Histogram bucket count**
{% /dt %}

{% dd %}
Each histogram datapoint is validated on ingestion, with a maximum per-bucket count (the number of observations in any single bucket) of 2,147,483,647 (231 − 1). If any bucket exceeds this, the entire datapoint is dropped.
{% /dd %}

{% /dl %}

## Further reading{% #further-reading %}

Additional helpful documentation, links, and articles:

- [Collector documentation](https://opentelemetry.io/docs/collector/)
- [Set up Log Collection](https://docs.datadoghq.com/opentelemetry/config/log_collection.md)
- [Configure Memory Limits](https://docs.datadoghq.com/opentelemetry/config/collector_batch_memory.md)
- [Enable the OTLP Receiver](https://docs.datadoghq.com/opentelemetry/config/otlp_receiver.md)
- [Install the DDOT Collector (Recommended)](https://docs.datadoghq.com/opentelemetry/setup/ddot_collector/install.md)
- [Feature Compatibility](https://docs.datadoghq.com/opentelemetry/compatibility.md)
- [OpenTelemetry Collector in Kubernetes](https://www.datadoghq.com/architecture/opentelemetry-collector-in-kubernetes/)
