Adding baggage limits for OT Baggage - #12303
Conversation
|
Hi! 👋 Thanks for your pull request! 🎉 To help us review it, please make sure to:
If you need help, please check our contributing guidelines. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1b4215ce74
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
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".
There was a problem hiding this comment.
More details
The shared limit accounting covers all changed extraction paths and preserves reserved Haystack trace identifiers.
🤖 Datadog Autotest · Commit 1b4215c · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
This comment has been minimized.
This comment has been minimized.
🟢 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. |
There was a problem hiding this comment.
Pull request overview
This PR adds configurable limits for legacy OpenTracing-style baggage extraction (including ot-baggage-* headers and equivalent baggage segments in other propagators) by centralizing baggage acceptance, byte-budgeting, and “reserved” key protection in ContextInterpreter, then updating codec implementations and tests accordingly.
Changes:
- Enforce
trace.baggage.max.itemsandtrace.baggage.max.bytesduring extraction across Datadog, W3C, X-Ray, and Haystack propagators. - Prevent caller-controlled baggage (including mapped baggage) from overwriting reserved propagation bookkeeping keys (e.g., Haystack lossless IDs).
- Add/extend extractor tests to validate item/byte truncation, replacement semantics, and reserved-key behavior.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java | Centralizes baggage limiting (items/bytes), replacement accounting, and reserved-key protection for extraction. |
| dd-trace-core/src/main/java/datadog/trace/core/propagation/DatadogHttpCodec.java | Routes OT baggage extraction through the new ContextInterpreter baggage limiter. |
| dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java | Routes OT baggage extraction through the new ContextInterpreter baggage limiter. |
| dd-trace-core/src/main/java/datadog/trace/core/propagation/XRayHttpCodec.java | Routes X-Ray “key=value” segment baggage extraction through the new limiter and preserves parsing after truncation. |
| dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java | Treats Haystack trace/span IDs as reserved baggage (non-evictable by caller baggage) while keeping Parent-ID subject to limits. |
| dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java | Adds tests for OT baggage item/byte limits, replacement semantics, and UTF-8 byte counting. |
| dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpExtractorTest.java | Adds tests for OT baggage item/byte truncation under W3C extraction. |
| dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpExtractorTest.java | Adds tests for X-Ray header baggage truncation and for continued parsing of trace context after truncation. |
| dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java | Adds tests ensuring reserved Haystack IDs survive baggage limits and mapped baggage cannot overwrite them. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💭 thought: I think the PR is confusing in multiple parts.
First the introduction of "reversed" baggage.
Then the tree map for the size. If it's only to keep track of the size, why don't we only compute the size of the evicted element to apply the difference? That would save the tree at the cost of duplicated key (which should only happen on rare occasion and never from the dd-trace-* SDK as defined by spec).
Then the variables are now confusing: baggage should be baggageItems, and baggageItems should be baggageItemCount, etc... But getting rid of the baggageItemBytes would help.
| final String decodedValue = HttpCodec.decode(value); | ||
| if (baggage.isEmpty()) { | ||
| baggage = new TreeMap<>(); | ||
| baggageItemBytes = new TreeMap<>(); |
There was a problem hiding this comment.
❔ question: Why do we need ordering here? (TreeMap)
There was a problem hiding this comment.
TreeMap was used in the old diff when OT Baggage was introduced, so I kept it here. Unsure of reasons it was used then (commit message says "use TreeMap everywhere for now"), but if unnecessary I can replace it w/ a HashMap.
| // that caller-supplied headers cannot evict it. Exempt from the configured limits, but not | ||
| // unbounded: the value is capped here rather than left to each caller to validate, so the total | ||
| // retained stays within trace.baggage.max.bytes plus a fixed amount per reserved key. | ||
| protected final void addReservedBaggageItem(String key, String value) { |
There was a problem hiding this comment.
💭 thought: I don't get the whole reserved baggage… If it's only for XRay and in case of conflict, I don't see the point having it.
There was a problem hiding this comment.
Moving to HaystackHttpCodec.java.
It's needed because Haystack has no limit to what size the traceID/spanID headers are. We can only hold 64 bits, so the rest of the header was historically stored in OT baggage.
Now that we introduce limits for OT baggage, we risk dropping the traceID/spanID items, which would break context propagation downstream. However, I made a change to no longer remove an already parsed baggage item, and instead allow going over the limits for reserved items (e.g. traceID/spanID).
Note: I still enforce a max length of 64 characters for reserved items so we don't store extremely large values.
Replace okio Utf8.size with String.length() for baggage size accounting, and normalize negative trace.baggage.max.* values to 0 in Config with a warning. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
More details
The item and byte limits reset for each extraction. Haystack now uses the first trace ID and span ID in a comma-separated header.
🤖 Datadog Autotest · Commit f1e2f2b · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
Disambiguates the running item counter from the baggage map itself, and from DDSpanContext.baggageItems which holds a map rather than a count. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What Does This Do
This PR adds limits to the size and number of objects allowed to be extracted for the legacy OT Baggage. However, Haystack has no size limit for traceID/spanID, and uses baggage to store the full header that can't be stored with DDTraceID. Enforcing limits may drop these keys, so reserved baggage items are necessary to ensure that context propagation is not broken.
This PR also fixes an old bug where comma-concatenated Haystack traceID/spanID/parentID headers were parsed using the entire header value, causing context extraction to fail. We now parse and preserve only the first traceID/spanID/parentID from the headers.
Finally, max baggage items and size config values are forced to 0 if a negative value is set.
Motivation
Additional Notes
Contributor Checklist
type:and (comp:orinst:) labels in addition to any other useful labelsclose,fix, or any linking keywords when referencing an issueUse
solvesinstead, and assign the PR milestone to the issueJira ticket: [PROJ-IDENT]