feat(trace-utils): add v1-native JSON log encoder brick - #2371
feat(trace-utils): add v1-native JSON log encoder brick#2371anais-raison wants to merge 6 commits into
Conversation
Isolated brick for APMSP-2812: adds a v1::Span-native JSON log encoder (span_v1.rs) alongside the existing v0.4 one, plus write_log_traces_v1 in log_writer.rs. Not wired into any live send path yet.
📚 Documentation Check Results📦
|
🔒 Cargo Deny Results📦
|
|
BenchmarksComparisonBenchmark execution time: 2026-09-01 13:03:41 Comparing candidate commit 946a530 in PR branch Found 14 performance improvements and 11 performance regressions! Performance is the same for 115 metrics, 0 unstable metrics.
|
Artifact Size Benchmark Reportaarch64-alpine-linux-musl
aarch64-unknown-linux-gnu
libdatadog-x64-windows
libdatadog-x86-windows
x86_64-alpine-linux-musl
x86_64-unknown-linux-gnu
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 058ae9c80b
ℹ️ 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".
| let merged_attrs = span_attrs_dd | ||
| .iter() | ||
| .filter(|(k, _)| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow())) | ||
| .chain(chunk.attrs_dd.iter().filter(|(k, _)| { | ||
| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow()) | ||
| && !span_attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| })) | ||
| .chain(chunk.payload_attrs_dd.iter().filter(|(k, _)| { | ||
| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow()) | ||
| && !span_attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| && !chunk.attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| })); |
There was a problem hiding this comment.
Approved with the reserve that this should be removed at the same time as the one for the agentless JSON encoder and we should do a promotion pass before encoding
There was a problem hiding this comment.
🟡 Changes recommended
The new v1 encoder currently performs O(n²) attribute precedence checks during serialization, which is avoidable and could become a hot-path performance issue once wired into production.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
| let span_attrs_dd = span.attributes.defensive_dedup(); | ||
| // Precedence: span attributes override chunk attributes override payload | ||
| // attributes. Attributes sharing a name with a "promoted" dedicated field are | ||
| // dropped so the dedicated field always wins and each key is written at most once. | ||
| let merged_attrs = span_attrs_dd | ||
| .iter() | ||
| .filter(|(k, _)| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow())) | ||
| .chain(chunk.attrs_dd.iter().filter(|(k, _)| { | ||
| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow()) | ||
| && !span_attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| })) | ||
| .chain(chunk.payload_attrs_dd.iter().filter(|(k, _)| { | ||
| !PROMOTED_ATTR_KEYS.contains(&(*k).borrow()) | ||
| && !span_attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| && !chunk.attrs_dd.iter().any(|(k2, _)| k2 == *k) | ||
| })); |
| assert_eq!(span["duration"], 500); | ||
| // `error` is always present as an integer, even when false. | ||
| assert_eq!(span["error"], 0); | ||
| // Optional fields must be absent when their underlying value is zero/empty. |
What does this PR do?
Adds a v1-native equivalent of the existing v0.4 JSON log encoder, as groundwork for making
v1::Span/v1::TraceChunkthe exporter's canonical internal type:json_log_encoder::span_v1+encode_traces_v1(libdd-trace-utils)write_log_traces_v1(libdd-data-pipeline)Nothing is wired into the live pipeline yet.
Motivation
Part of APMSP-2812: migration of the exporter from v0.4 to v1 with isolated bricks first before one final breaking PR that will handle the actual swap.
Additional Notes
Pure addition, no behavior change — these functions aren't called anywhere yet, so there's no regression risk.