Remove containerTagsHash/processTags from DSM primary pathway hash - #12573
arjunguhaswe wants to merge 11 commits into
Conversation
DataStreamsTags seeded its primary pathway hash from BaseHash.getBaseHash(), a global static shared with DBM that folds in serviceName+env+primaryTag plus process tags and the Agent-reported containerTagsHash. The latter two are DBM-oriented (per-container SQL attribution) and change on every rolling deploy, so the same logical DSM edge was producing a new pathway hash on every deploy, inflating block_on_hashes cardinality with no real fan-out. BaseHash now also exposes an identity-only hash (service+env+primaryTag), which DSM's primary hash is seeded from; getBaseHash() is untouched so DBM's SQL-comment injection keeps its existing per-container behavior. containerTagsHash and process tags are instead folded into DataStreamsTags.aggregationHash/completeHash, independently of each other, mirroring the datasetName fix in bd3f6f5. DSM2-335 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
They were never decoded into discrete tags by the backend, so folding them into aggregationHash only added opaque cardinality with no user-visible benefit. Leaves a TODO to tag a DSM backend owner before this ships, since raphaelgavache flagged a related concern in PR #9282 that was never answered. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🟢 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. |
…ntainertagshashprocesstags-from-dsm
Testing evidenceRan the repro against the Data Streams Sandbox account (metrics collection happens in the Datadog HQ / org2 account). Before (unpatched — primary hash fragments on rolling deploy) After (with this fix — primary hash stable across rolling deploy) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1ac2f088e8
ℹ️ 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".
AlexeyKuznetsov-DD
left a comment
There was a problem hiding this comment.
Left minor comments.
internal-api unit tests should be JUnit 5 per AGENTS.md; the Spock suites in BaseHashTest.groovy/DataStreamsTagsTest.groovy predate that convention, so leave them as-is and add the new coverage in new JUnit 5 files instead of extending them further. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
service/env/primaryTag are fixed for the JVM's lifetime once Config is built, so recomputing identityHash inside recalc() on every containerTagsHash/processTags change was redundant. Compute it once at class-load instead; calcIdentity is now package-private so it can be exercised directly in tests without forcing a Config-driven recompute. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AlexeyKuznetsov-DD
left a comment
There was a problem hiding this comment.
LGTM from LP side, but I think it make sense to get an approval from DSM/IDM too?
…ckpoint BaseHash's class initializer (and therefore identityHash's snapshot of Config.get().getServiceName()/getEnv()/getPrimaryTag()) can run early as a side effect of unrelated static initialization - DefaultDataStreamsMonitoring's REPORT/POISON_PILL fields reference DataStreamsTags.EMPTY, which forces BaseHash to load. Since identityHash is now calculated once, that snapshot could be permanently stale if it's taken before Config settles. Add BaseHash.ensureIdentityHash(), a one-time guard that recalculates identityHash from the current Config, and call it right before the first outbound DSM checkpoint's tags are created in DefaultDataStreamsMonitoring.setProduceCheckpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Concurrent callers all recompute from the same Config, so a race just means a few redundant, identical writes - not worth the lock contention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…inel No need for a separate boolean guard - identityHash is either "not yet computed" (0) or holds a real value, so getIdentityHash() can just check for that directly. This also removes the need for an explicit BaseHash.ensureIdentityHash() call site in DefaultDataStreamsMonitoring.setProduceCheckpoint, since every checkpoint (inbound or outbound) already reads getIdentityHash() via DataStreamsTags. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ntainertagshashprocesstags-from-dsm
|
|
||
| // once non-zero, later reads don't recalculate - a caller that needs a fresh value can | ||
| // still force one directly (e.g. tests via updateIdentityHash) | ||
| BaseHash.updateIdentityHash(42L); |
There was a problem hiding this comment.
getIdentityHashRecalculatesFromConfigWhenUnset ends by calling BaseHash.updateIdentityHash(42L) and never resets it afterward. Since this class isn't forked per-method and JUnit 5 doesn't guarantee method order, if this test runs before identityHashIsUnaffectedByContainerTagsHashOrProcessTags, the latter's getIdentityHash() calls will return the stale 42 (the identityHash == 0 lazy-init guard never fires) — so that test would pass even if a real regression reintroduced container-tags-hash/process-tags into the identity hash, which is the exact bug this PR fixes. Consider resetting identityHash (e.g. via a test hook that sets it back to 0 or recomputes via calcIdentity()) in an @AfterEach.
There was a problem hiding this comment.
ditto, great catch, will fix before merge.
| def two = getTags(0) | ||
|
|
||
| BaseHash.updateBaseHash(12) | ||
| BaseHash.updateIdentityHash(12) |
There was a problem hiding this comment.
Same root cause as in BaseHashIdentityTest: 'test service name override and global hash' calls BaseHash.updateIdentityHash(12), but cleanup() only resets baseHash/lastContainerTagsHash via recalcBaseHash(null) — identityHash is left stuck at 12 for the rest of the test JVM. Doesn't break current assertions since they're relative, but it's a latent leak that could mask failures in a future test asserting an exact identity-hash value. Worth resetting identityHash in cleanup() too.
There was a problem hiding this comment.
Great catch, will fix before merge.
|
Just looking at description of the PR, but |
|
@piochelepiotr -- the tag causing that is |
Summary
Fixes DSM2-335: DSM's primary pathway
hashwas seeded fromBaseHash.getBaseHash(), a global static shared with DBM that folds inserviceName + env + primaryTag + processTags + containerTagsHash.containerTagsHashis derived by the local Agent fromkube_replica_setand changes on every rolling deploy;processTagsis enabled by default. SinceDDAgentFeaturesDiscovery.processInfoResponseHeaders()recalculatesBaseHashunconditionally whenever the Agent reports a new container-tags hash, the same logical DSM edge (same service, same topic, same direction) was producing a new pathwayhashon every rolling deploy — permanently inflatingblock_on_hashescardinality with no real fan-out.Testing evidence
Ran the repro against the Data Streams Sandbox account (metrics collection happens in the Datadog HQ / org2 account).
Before (unpatched — primary hash fragments on rolling deploy)
Testing Run (Data Streams Prod)
Dropped Payload Metrics (Org2)
After (with this fix — primary hash stable across rolling deploy)
Testing Run (Data Streams Prod)
Dropped Payload Metrics (Org2)
Test plan
BaseHashTest: identity hash tracks service/env/primaryTag but is unaffected by container-tags hash or process tagsDataStreamsTagsTest: container-tags hash / process tag changes affectaggregationHash/completeHashbut not the primaryhash(the DSM2-335 regression tests)DefaultPathwayContextTestupdated to seed via the newBaseHash.updateIdentityHash()test hookSQLCommenterTestsuite (DBM, 91 tests) passes unmodified — confirmsBaseHash.getBaseHash()behavior for DBM is untoucheddatasetNamebug is an equally plausible explanation for versions before that🤖 Generated with Claude Code