Skip to content

Commit 45636bc

Browse files
bm1549claude
andcommitted
Replace non-functional SEQUENTIAL config with RANDOM ID reproduction test
Remove injectSysConfig("id.generation.strategy", "SEQUENTIAL") which did not actually trigger the flake. Add KafkaClientDsmDisabledRandomIdsForkedTest that overrides idGenerationStrategyName() to "RANDOM", matching production behavior. With RANDOM IDs, SORT_TRACES_BY_ID produces non-deterministic order, causing the original positional consumer-to-producer mapping to fail ~95% of the time. Switch the batch consume test to SORT_TRACES_BY_START so the parent trace (started before any consumer receives messages) is always at index 0. The dynamic parent lookup fix handles any ordering of the 3 consumer traces. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8d3542c commit 45636bc

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

dd-java-agent/instrumentation/kafka/kafka-clients-0.11/src/test/groovy/KafkaClientTestBase.groovy

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,10 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase {
898898
}
899899
assert receivedSet.isEmpty()
900900

901-
assertTraces(4, SORT_TRACES_BY_ID) {
901+
// Use SORT_TRACES_BY_START so the parent trace (started first, before any consumer
902+
// receives messages) is always at index 0 regardless of span ID generation strategy.
903+
// The dynamic parent lookup below handles any ordering of the 3 consumer traces.
904+
assertTraces(4, SORT_TRACES_BY_START) {
902905
trace(7) {
903906
basicSpan(it, "parent")
904907
basicSpan(it, "producer callback", span(0))
@@ -923,7 +926,7 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase {
923926
queueSpan(it, trace(0)[2])
924927
}
925928
} else {
926-
// Consumer traces are sorted by random span ID, so we can't assume a fixed
929+
// Consumer traces are sorted by start time, so we can't assume a fixed
927930
// mapping between consumer trace index and producer span index. Instead, find
928931
// the actual parent producer span for each consumer trace dynamically.
929932
def producerSpans = [trace(0)[2], trace(0)[4], trace(0)[6]]
@@ -1481,10 +1484,6 @@ class KafkaClientDataStreamsDisabledForkedTest extends KafkaClientTestBase {
14811484
super.configurePreAgent()
14821485
injectSysConfig("dd.service", "KafkaClientDataStreamsDisabledForkedTest")
14831486
injectSysConfig("dd.kafka.legacy.tracing.enabled", "true")
1484-
// Deterministic reproduction: SEQUENTIAL ID strategy forces a known sort order
1485-
// that differs from the reverse order the original positional code assumed,
1486-
// proving the dynamic parent lookup fix handles any ordering.
1487-
injectSysConfig("id.generation.strategy", "SEQUENTIAL")
14881487
}
14891488

14901489
@Override
@@ -1515,3 +1514,24 @@ class KafkaClientContextSwapForkedTest extends KafkaClientV0ForkedTest {
15151514
injectSysConfig(TraceInstrumentationConfig.LEGACY_CONTEXT_MANAGER_ENABLED, "false")
15161515
}
15171516
}
1517+
1518+
/**
1519+
* Reproduces the flake in "test spring kafka template produce and batch consume"
1520+
* by using RANDOM IDs (instead of the default SEQUENTIAL used in tests).
1521+
*
1522+
* Root cause: The test's assertTraces(4, SORT_TRACES_BY_ID) sorts traces by
1523+
* localRootSpan.spanId, then hardcodes positional mappings between consumer and
1524+
* producer traces. With SEQUENTIAL IDs (the test default), both the producer span
1525+
* finish order within trace(0) and the consumer trace sort order are driven by the
1526+
* same Kafka internal ordering, so the mapping happens to be consistent.
1527+
*
1528+
* With RANDOM IDs (as used in production), the sort order becomes non-deterministic.
1529+
* There are 3! = 6 possible orderings for the 3 consumer traces, and only 1 matches
1530+
* the hardcoded mapping. The dynamic parent lookup fix handles any ordering.
1531+
*/
1532+
class KafkaClientDsmDisabledRandomIdsForkedTest extends KafkaClientDataStreamsDisabledForkedTest {
1533+
@Override
1534+
protected String idGenerationStrategyName() {
1535+
return "RANDOM"
1536+
}
1537+
}

0 commit comments

Comments
 (0)