Stamp _dd.apm.enabled on every exported chunk when APM tracing is disabled#12028
Stamp _dd.apm.enabled on every exported chunk when APM tracing is disabled#12028claponcet wants to merge 4 commits into
Conversation
…abled Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🎯 Code Coverage (details) 🔗 Commit SHA: 3258ce2 | Docs | Datadog PR Page | Give us feedback! |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
| } | ||
| } | ||
|
|
||
| @GetMapping("/late-outbound") |
There was a problem hiding this comment.
Very nice, I appreciate the test case for this
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
What Does This Do
When APM tracing is disabled (
DD_APM_TRACING_ENABLED=false, i.e. standalone ASM), this stamps the_dd.apm.enabled:0billing marker on the root-most span(s) of every exported trace chunk at export time (CoreTracer.write), instead of setting it once on the local root span at creation (Config.getLocalRootSpanTags()).For each exported chunk:
This deliberately does not rely on span ordering: the local root is not necessarily the first span in finish order for asynchronous frameworks.
Motivation
Standalone ASM customers rely on
_dd.apm.enabled:0to opt out of APM host billing: the intake bills a trace chunk unless at least one of its spans carries the marker.Previously the marker lived only on the trace's local root span, on the assumption that the local root is present in every exported chunk. That assumption breaks in two ways:
http.request) flushes later, alone, in a separate chunk with no marker.In both cases the intake charges APM host billing for an ASM-only service. Making the decision at chunk-export time — the one place that unambiguously knows chunk boundaries — guarantees every exported chunk carries the marker. This mirrors the equivalent Node.js fix (dd-trace-js#9483).
Additional Notes
The marker is now stamped after the sampling decision and only when APM tracing is disabled, so there is no effect on the default (APM-enabled) hot path. The fallback's array allocation and sort run only in the cold path (APM disabled + a multi-span chunk exported without its local root).
Covered at two levels:
ApmTracingDisabledChunkMarkerTest(dd-trace-core) — a deterministic unit reproduction of the split-chunk case, a positive single-chunk control that isolates chunk-splitting as the cause, and a case where the local root is not first in finish order (guarding against marking merelychunk.get(0))./late-outboundendpoint and smoke test in theapm-tracing-disabledmodule that exercises a real delayed outbound child flushed alone in its own chunk.Contributor Checklist
type:and (comp:orinst:) labels in addition to any other useful labelsclose,fix, or any linking keywords when referencing an issueJira ticket: APPSEC-69334