fix(ddtrace/tracer): pre-compute _dd.p.dm numeric value at write-time#4576
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files
🚀 New features to boost your workflow:
|
|
✅ Tests 🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: 1be56bb | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback! |
BenchmarksBenchmark execution time: 2026-03-25 09:38:05 Comparing candidate commit 1be56bb in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 215 metrics, 9 unstable metrics.
|
…` in the conditional body Co-authored-by: Benjamin De Bernardi <[email protected]>
…com:Datadog/dd-trace-go into dario.castane/langplat-59/no-parseint-on-dm
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f6898ef772
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| log.Error("failed to convert decision maker to uint32: %s", err.Error()) | ||
| } | ||
| } | ||
| sm = span.context.trace.decisionMaker() |
There was a problem hiding this comment.
Preserve
_dd.p.dm when encoding chunks from generic contexts
payloadV1.push now reads only trace.decisionMaker(), but the cache is not initialized on every path that sets propagating tags. In particular, FromGenericCtx assigns sc.trace.propagatingTags = ctx.PropagatingTags() directly (without calling setPropagatingTagLocked/replacePropagatingTags), so traces built from generic contexts that carry _dd.p.dm will emit samplingMechanism=0 instead of the propagated value. Before this commit, push parsed _dd.p.dm from the tags map at flush time, so this is a behavior regression for that integration path.
Useful? React with 👍 / 👎.
…eneric span contexts
…com:Datadog/dd-trace-go into dario.castane/langplat-59/no-parseint-on-dm
2a2cae7 to
1be56bb
Compare
|
/merge |
|
View all feedbacks in Devflow UI.
This pull request is not mergeable according to GitHub. Common reasons include pending required checks, missing approvals, or merge conflicts — but it could also be blocked by other repository rules or settings.
The expected merge time in
|
…me (#4576) ### What does this PR do? Moves the `strconv.ParseInt` call for `_dd.p.dm` (decision maker) out of the v1 payload flush path and into the write path. A `dm uint32` field is added to the `trace` struct. It is kept in sync with `propagatingTags[keyDecisionMaker]` at all mutation sites (`setPropagatingTagLocked`, `unsetPropagatingTagLocked`, `replacePropagatingTags`). A shared `unsetPropagatingTagLocked` helper is introduced so the delete-and-clear logic is not duplicated between `unsetPropagatingTag` and `setSamplingPriorityLockedWithForce`. `payloadV1.push` now reads the pre-computed value via `trace.decisionMaker()` instead of fetching the string from the propagating tags map and parsing it on every flush. ### Motivation `payloadV1.push` is called once per finished trace chunk. On every call it was acquiring a read lock, doing a map lookup, and then running `strconv.ParseInt` — all to read a value that was set at most once or twice during the lifetime of the trace. Moving the parse to write-time eliminates the per-flush map lookup and parse, replacing them with a single scalar read behind an `RLock`. ### Reviewer's Checklist - [x] Changed code has unit tests for its functionality at or near 100% coverage. - [x] New code is free of linting errors. You can check this by running `make lint` locally. - [x] New code doesn't break existing tests. You can check this by running `make test` locally. - [x] Add an appropriate team label so this PR gets put in the right place for the release notes. - [x] All generated files are up to date. You can check this by running `make generate` locally. Co-authored-by: dario.castane <[email protected]>
What does this PR do?
Moves the
strconv.ParseIntcall for_dd.p.dm(decision maker) out of the v1 payload flush path and into the write path.A
dm uint32field is added to thetracestruct. It is kept in sync withpropagatingTags[keyDecisionMaker]at all mutation sites (setPropagatingTagLocked,unsetPropagatingTagLocked,replacePropagatingTags). A sharedunsetPropagatingTagLockedhelper is introduced so the delete-and-clear logic is not duplicated betweenunsetPropagatingTagandsetSamplingPriorityLockedWithForce.payloadV1.pushnow reads the pre-computed value viatrace.decisionMaker()instead of fetching the string from the propagating tags map and parsing it on every flush.Motivation
payloadV1.pushis called once per finished trace chunk. On every call it was acquiring a read lock, doing a map lookup, and then runningstrconv.ParseInt— all to read a value that was set at most once or twice during the lifetime of the trace. Moving the parse to write-time eliminates the per-flush map lookup and parse, replacing them with a single scalar read behind anRLock.Reviewer's Checklist
make lintlocally.make testlocally.make generatelocally.