Set Up the OpenTelemetry Collector
This product is not supported for your selected
Datadog site. (
).
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) instead.
The configurations on this page use the agent deployment pattern: 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. 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.
For cluster-wide Kubernetes metrics and Kubernetes Explorer, see Kubernetes Metrics.
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 under OTel SDK + Upstream OpenTelemetry Collector.
1. Download the OpenTelemetry Collector
Download the latest release of the OpenTelemetry Collector Contrib distribution from the releases page.
Select the tab for your environment.
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.
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 for an optional config to gather additional metadata about the system.
Run the Collector:
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
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_SITEOTEL_RESOURCE_ATTRIBUTES: The Collector cannot detect host information from inside a container, so provide it here (for example, host.name=<YOUR_HOST_NAME>).
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:
docker network create otel
Run the Collector with the host filesystem mounted, attached to that network:
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
Use the official OpenTelemetry Collector Helm chart 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.
To collect cluster-wide metrics or send Kubernetes resource data to Kubernetes Explorer, deploy a cluster Collector alongside the DaemonSet. See [Kubernetes Metrics][13].
Create a Kubernetes secret with your Datadog API key:
kubectl create secret generic datadog-secrets --from-literal=api-key='<YOUR_API_KEY>'
Add the OpenTelemetry Helm repository:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
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.
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.
Install the Collector:
helm install otelcol open-telemetry/opentelemetry-collector --version 0.147.1 --values values.yaml
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_SITEK8S_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.
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 for RBAC setup instructions, and add nodes/stats to the rules it lists.
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
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
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
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
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
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.
Configure your OpenTelemetry-instrumented application to send data to the Collector. Set the OTEL_EXPORTER_OTLP_ENDPOINT environment variable to point to the Collector:
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
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.
For Kubernetes environments where the Helm values enable host ports, configure the endpoint using the host IP:
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).
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, which correlates your traces, metrics, and logs.
Verify the setup
After your application sends telemetry to the Collector, verify that data appears in Datadog:
- In Datadog, go to APM > Services and confirm that your
service.name appears. - Open APM > Traces and search for your service.
- 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. - If you send logs through OTLP, go to Logs Explorer and search for your service name.
- In Fleet Automation, confirm that the Collector and its configuration appear.
Key components
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 also show how to replace groups of container tag dimensions with glob patterns, such as - glob: container.**.
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.
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:
{
"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
}
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.
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
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 project and handles API key validation and deployment type reporting.
Cumulative-to-delta processor
The cumulativetodelta processor converts cumulative metrics to delta temporality, which is Datadog’s recommended configuration for OpenTelemetry metrics.
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
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
Datadog enforces the following limits when ingesting OTLP data. Data that exceeds a limit is rejected or dropped as noted.
- Payload size
- 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. - Histogram bucket count
- 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.
Further reading
Additional helpful documentation, links, and articles: