Introduction
Running the Datadog Agent on every node is convenient, but it also means host-based billing kicks in—even if you only need a handful of custom metrics. One way to cut those costs is to replace the Agent with the OpenTelemetry (OTel) Collector Contrib build and send your metrics through the Datadog exporter.
This guide walks through a minimal proof-of-concept on an EC2 instance using:
- The OTel Collector Contrib RPM package
- A collector
config.yaml
that adds EC2 metadata and forwards to Datadog - A tiny Python app that emits OTLP metrics
- Validation inside the Datadog UI
Goal: Confirm that metrics reach Datadog without the Datadog Agent so you avoid host fees.
Prerequisites
- EC2 instance (x86-64 or ARM64) with outbound internet or proxy access to us5.datadoghq.com
- Datadog API key exported as
DD_API_KEY
- Root or sudo privileges
- Python 3.10+ (only for the test app)
1. Install the OpenTelemetry Collector Contrib
# For x86-64 / AMD64
sudo yum install -y \
https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.131.1/otelcol-contrib_0.131.1_linux_amd64.rpm
# For ARM64 (Graviton, Apple Silicon, etc.)
# sudo yum install -y \
# https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.131.1/otelcol-contrib_0.131.1_linux_arm64.rpm
RPMs place the binary at /usr/bin/otelcol-contrib
and create a systemd unit called otelcol-contrib.service
.
2, Create config.yaml
Save the following to /etc/otelcol-contrib/config.yaml.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
resourcedetection/env:
detectors: [env]
resourcedetection/ec2:
detectors: ["ec2"]
ec2:
tags: ["^.*$"]
max_attempts: 5
transform/remove_ec2_tag_prefix:
error_mode: ignore
metric_statements:
- context: resource
statements:
- replace_all_patterns(resource.attributes, "key", "^ec2\\.tag\\.(.*)$", "$1")
batch:
send_batch_size: 10
send_batch_max_size: 100
timeout: 10s
exporters:
datadog:
api:
site: us5.datadoghq.com
key: ${env:DD_API_KEY}
host_metadata:
enabled: false
metrics:
resource_attributes_as_tags: true
histograms:
mode: distributions
extensions:
health_check: {}
pprof: {}
zpages: {}
service:
extensions: [health_check, pprof, zpages]
pipelines:
metrics:
receivers: [otlp]
processors: [resourcedetection/env, resourcedetection/ec2, transform/remove_ec2_tag_prefix, batch]
exporters: [datadog]
resourcedetection/ec2
adds host.name
, cloud.region
, and EC2 tags so your metrics retain the same context you’re used to.
3. Start (and enable) the Collector
sudo /usr/bin/otelcol-contrib --config /etc/otelcol-contrib/config.yaml
# Or run permanently via systemd
sudo systemctl enable --now otelcol-contrib
sudo systemctl status otelcol-contrib
You should see a log line similar to:
Exporter datadog/exporter is starting with endpoint us5.datadoghq.com:443
4. Send a test metric from Python
Install the required libs:
python -m pip install "opentelemetry-sdk~=1.25" \
"opentelemetry-exporter-otlp~=1.25"
Create send_metric.py:
from opentelemetry import metrics
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
EXPORTER = OTLPMetricExporter(endpoint="http://localhost:4317", insecure=True)
reader = PeriodicExportingMetricReader(EXPORTER, export_interval_millis=5000)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = metrics.get_meter("demo.metric.sender")
counter = meter.create_counter(
name="demo_custom_metric",
unit="1",
description="Custom metric sent via OTel"
)
# Add one data point
counter.add(1, {"env": "demo", "app": "cost-savings"})
print("Metric sent!")
You should see Metric sent! and the Collector logs should show an OTLP request followed by a Datadog export.
5. Verify in Datadog
Open Metrics Explorer.
Search for demo_custom_metric.
Set the graph to Sum per minute and choose the right time window.