feat(otel): add Datadog fan-out collector config + local traces pipeline#374
feat(otel): add Datadog fan-out collector config + local traces pipeline#374NiteshDhanpal wants to merge 1 commit into
Conversation
Adds otel-collector-config.datadog.yaml: an opt-in collector config that duplicates traces and metrics to BOTH the LGTM path and Datadog. This is the "collector sink" phase of the ddtrace -> LGTM migration -- once the app stops emitting to Datadog directly via ddtrace, the collector keeps Datadog fed, so there is no gap. One OTel SDK produces the spans, so the same trace_id is exported to both backends. Also adds a traces pipeline to the default local collector config (it only had metrics), so OTel traces emitted by the app are handled locally instead of dropped. The Datadog fan-out is opt-in (mount the .datadog.yaml file; requires DD_API_KEY + optional DD_SITE) and does not change the default keyless local collector. It is the reference pattern for the Helm-managed production collector. Migration-safety note is documented in the file header: deploy + verify the Datadog fan-out in an environment BEFORE disabling app-side ddtrace there. Co-Authored-By: Claude Opus 4.8 <[email protected]>
| # - Optionally set TEMPO_OTLP_ENDPOINT to also fan traces out to Tempo; if | ||
| # unset, the Tempo exporter is simply not referenced (see pipelines below). |
There was a problem hiding this comment.
TEMPO_OTLP_ENDPOINT comment implies conditional behaviour that doesn't exist
The requirements header says "Optionally set TEMPO_OTLP_ENDPOINT to also fan traces out to Tempo; if unset, the Tempo exporter is simply not referenced." However, no otlp/tempo exporter is defined in exporters: and no pipeline references it — the env var does nothing right now. An operator who reads this, sets TEMPO_OTLP_ENDPOINT, and deploys will get silent loss of the expected Tempo routing with no error from the collector. The phrase "if unset, the Tempo exporter is simply not referenced" actively suggests conditional logic that doesn't exist yet. Consider rewording to "Tempo fan-out is not yet implemented — see follow-up ticket" to avoid the false impression.
Prompt To Fix With AI
This is a comment left during a code review.
Path: agentex/otel/otel-collector-config.datadog.yaml
Line: 15-16
Comment:
**TEMPO_OTLP_ENDPOINT comment implies conditional behaviour that doesn't exist**
The requirements header says "Optionally set `TEMPO_OTLP_ENDPOINT` to also fan traces out to Tempo; if unset, the Tempo exporter is simply not referenced." However, no `otlp/tempo` exporter is defined in `exporters:` and no pipeline references it — the env var does nothing right now. An operator who reads this, sets `TEMPO_OTLP_ENDPOINT`, and deploys will get silent loss of the expected Tempo routing with no error from the collector. The phrase "if unset, the Tempo exporter is simply not referenced" actively suggests conditional logic that doesn't exist yet. Consider rewording to "Tempo fan-out is not yet implemented — see follow-up ticket" to avoid the false impression.
How can I resolve this? If you propose a fix, please make it concise.| debug: | ||
| verbosity: normal |
There was a problem hiding this comment.
Debug exporter lacks sampling — will log every span and metric in production
The local config (otel-collector-config.yaml) configures sampling_initial: 5 and sampling_thereafter: 200 on the debug exporter, capping console output at about 1-in-200 records after warmup. The Datadog fan-out config, described as "the reference pattern for the Helm-managed production collector," omits those settings. With verbosity: normal, every span in the traces pipeline and every metric data point in the metrics pipeline will be printed to stdout. In a staging or production deployment this generates significant log volume and cost. Either add the same sampling knobs or remove debug from the Datadog-facing pipelines if console output isn't useful there.
Prompt To Fix With AI
This is a comment left during a code review.
Path: agentex/otel/otel-collector-config.datadog.yaml
Line: 42-43
Comment:
**Debug exporter lacks sampling — will log every span and metric in production**
The local config (`otel-collector-config.yaml`) configures `sampling_initial: 5` and `sampling_thereafter: 200` on the `debug` exporter, capping console output at about 1-in-200 records after warmup. The Datadog fan-out config, described as "the reference pattern for the Helm-managed production collector," omits those settings. With `verbosity: normal`, every span in the `traces` pipeline and every metric data point in the `metrics` pipeline will be printed to stdout. In a staging or production deployment this generates significant log volume and cost. Either add the same sampling knobs or remove `debug` from the Datadog-facing pipelines if console output isn't useful there.
How can I resolve this? If you propose a fix, please make it concise.
stephen-wang24
left a comment
There was a problem hiding this comment.
Can you also add a note how it was tested locally?
What this PR does
Adds the Datadog fan-out for the OTel Collector — the "collector sink" phase of the ddtrace → LGTM migration.
agentex/otel/otel-collector-config.datadog.yaml— opt-in collector config that duplicates traces + metrics to both the LGTM path (Prometheus/Tempo) and Datadog (datadogexporter). One OTel SDK produces the spans, so the sametrace_idis exported to both backends.agentex/otel/otel-collector-config.yaml— adds atracespipeline to the default local config (it previously had metrics only), so OTel traces emitted by the app are handled locally instead of dropped.Why
Once the app stops emitting to Datadog directly via
ddtrace(later in the migration), Datadog must be fed somewhere or coverage goes dark. Feeding it from the collector keeps Datadog whole while the app moves to a single OTel SDK.Safety / rollout
DD_API_KEY(+ optionalDD_SITE, defaultdatadoghq.com). The default local collector stays keyless and unchanged.otel/opentelemetry-collector-contribimage already run by docker-compose (datadog exporter included).Verification
Both YAML files parse; pipelines/exporters confirmed (
metrics/tracespresent;datadogexporter wired into both pipelines in the fan-out file).Follow-up (not in this PR)
Add an OTLP/Tempo trace exporter to the fan-out
tracespipeline once a Tempo endpoint is available (placeholder documented in the file).Greptile Summary
This PR advances the ddtrace → LGTM migration by adding an opt-in OTel Collector config (
otel-collector-config.datadog.yaml) that fans traces and metrics to both Datadog and the LGTM stack from a single OTel SDK, and by wiring up atracespipeline in the default local collector config that previously only handled metrics.otlpreceiver,batchprocessor, andprometheus+datadog+debugexporters; bothtracesandmetricspipelines are populated. RequiresDD_API_KEY;DD_SITEdefaults todatadoghq.com. Intended as the reference pattern for the Helm-managed production collector.tracespipeline (receiver → batch → debug) so OTel traces are no longer silently dropped during local development.Confidence Score: 4/5
Safe to merge; the Datadog fan-out is completely opt-in and the default local config change is additive only.
The two files are YAML-only config changes with no code execution risk. The local config addition (traces pipeline) is trivially correct. The Datadog fan-out file is well-structured and the migration safety note is explicit. Two quality issues are worth addressing before this file is promoted to staging: the misleading TEMPO_OTLP_ENDPOINT comment that implies conditional logic not yet implemented, and the debug exporter lacking the sampling guard that the local config uses — omitting it will produce unsampled console output for every span and metric in production deployments.
agentex/otel/otel-collector-config.datadog.yaml — the TEMPO_OTLP_ENDPOINT comment and the unsampled debug exporter warrant a second look before this file is mounted in staging or used as the Helm reference.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD App["App (OTel SDK)"] subgraph Default["Default Local Collector (otel-collector-config.yaml)"] OTLPLocal["OTLP Receiver\n(gRPC :4317 / HTTP :4318)"] BatchLocal["batch processor"] DebugLocal["debug exporter\n(verbosity: detailed + sampling)"] PromLocal["prometheus exporter\n(:8889)"] OTLPLocal --> BatchLocal BatchLocal -->|metrics| DebugLocal BatchLocal -->|metrics| PromLocal BatchLocal -->|traces| DebugLocal end subgraph Fanout["Datadog Fan-out Collector (otel-collector-config.datadog.yaml)"] OTLPFan["OTLP Receiver\n(gRPC :4317 / HTTP :4318)"] BatchFan["batch processor"] DebugFan["debug exporter\n(verbosity: normal)"] PromFan["prometheus exporter\n(:8889)"] DDExp["datadog exporter\n(DD_API_KEY + DD_SITE)"] OTLPFan --> BatchFan BatchFan -->|metrics| PromFan BatchFan -->|metrics| DDExp BatchFan -->|metrics| DebugFan BatchFan -->|traces| DDExp BatchFan -->|traces| DebugFan end App -->|"OTLP (local dev)"| OTLPLocal App -->|"OTLP (staging/prod opt-in)"| OTLPFan DDExp -->|"Datadog API"| DD[("Datadog")] PromFan --> Grafana[("Grafana / Prometheus")]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(otel): add Datadog fan-out collecto..." | Re-trigger Greptile