Skip to content

[WIP - DO NOT REVIEW] Add DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED for Kafka consumers#11993

Draft
bm1549 wants to merge 1 commit into
masterfrom
brian.marks/kafka-create-consumer-scope-flag
Draft

[WIP - DO NOT REVIEW] Add DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED for Kafka consumers#11993
bm1549 wants to merge 1 commit into
masterfrom
brian.marks/kafka-create-consumer-scope-flag

Conversation

@bm1549

@bm1549 bm1549 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

Adds an opt-in configuration flag, DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED (system property dd.trace.kafka.create-consumer-scope.enabled, default false), that keeps the last consumed record's kafka.consume span active past the end of the Kafka poll loop. With the flag on, work a consumer does after its per-record iterator loop (a common "buffer records in the loop, write to the DB after" pattern) nests under the consume span instead of starting a disconnected root trace.

The deferred span is finished by the next poll(), close(), or unsubscribe(), and by the existing root-iteration-scope keep-alive as a backstop if none arrive. Committing offsets is deliberately not treated as a close trigger. Cleanup is owner-aware: each consumer records the exact span it deferred on its KafkaConsumerInfo, so the span is finished correctly even when records are iterated on a different thread than the one that closes the consumer.

Implemented for both kafka-clients-0.11 and kafka-clients-3.8.

Motivation

When a consumer buffers records inside the iterator loop and does its real work after the loop, that work runs with no active consume scope. Downstream spans (for example JDBC) are parented to nothing and recorded as separate root traces rather than as children of the kafka.consume span, breaking the connected consume to process to downstream trace.

Additional Notes

  • Off by default; only engaged under the legacy context manager (the new context-swap manager has no equivalent cross-thread scope cleanup, so the flag is a no-op there).
  • Flag-on forked test variants (legacy and context-swap) cover post-loop reparenting, the per-trigger close semantics, the keep-alive backstop, and cross-thread (worker-thread) cleanup.

Contributor Checklist

  • Title formatted per the contribution guidelines
  • type: and inst: labels assigned
  • No close/fix/linking keywords used
  • Public documentation update for the new configuration flag (follow-up)

🤖 Generated with Claude Code

When a Kafka consumer buffers records inside the per-record iterator loop and
does its real work (for example a JDBC write) after the loop, that work runs
with no active consume scope, so its spans start a new root trace disconnected
from the kafka.consume span.

This adds an opt-in flag, DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED
(default false), that keeps the last record's kafka.consume span active past the
end of the poll loop so same-thread post-loop work nests under it. The deferred
span is finished on the next poll(), close(), or unsubscribe(); if none of those
arrive, the existing root-iteration-scope keep-alive finishes it as a backstop.
Committing offsets is deliberately not a close trigger.

The behavior is engaged only under the legacy context manager, whose ITERATION
scopes have native cross-thread-safe cleanup; it is a no-op under the new
context-swap manager. Cleanup is owner-aware: each consumer records a handle to
the span it deferred on its KafkaConsumerInfo, so the exact span is finished even
when records were iterated on a different thread than the one that triggers the
close.

Implemented for both kafka-clients-0.11 and kafka-clients-3.8, with flag-on
forked test variants (legacy and context-swap modes) covering post-loop
reparenting, the per-trigger close semantics, the keep-alive backstop, and
cross-thread cleanup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bm1549 bm1549 added type: feature Enhancements and improvements inst: kafka Kafka instrumentation tag: ai generated Largely based on code generated by an AI or LLM labels Jul 18, 2026
@datadog-prod-us1-6

This comment has been minimized.

@dd-octo-sts

dd-octo-sts Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 13.94 s 13.94 s [-0.6%; +0.7%] (no difference)
startup:insecure-bank:tracing:Agent 12.96 s 12.99 s [-0.9%; +0.5%] (no difference)
startup:petclinic:appsec:Agent 17.00 s 16.72 s [+0.7%; +2.7%] (maybe worse)
startup:petclinic:iast:Agent 16.90 s 16.90 s [-0.8%; +0.8%] (no difference)
startup:petclinic:profiling:Agent 16.81 s 16.88 s [-1.9%; +1.1%] (no difference)
startup:petclinic:sca:Agent 16.96 s 16.80 s [-0.0%; +1.9%] (no difference)
startup:petclinic:tracing:Agent 16.05 s 15.62 s [-1.6%; +7.1%] (no difference)

Commit: 712b7757 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

@pr-commenter

pr-commenter Bot commented Jul 18, 2026

Copy link
Copy Markdown

Kafka / producer-benchmark

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master brian.marks/kafka-create-consumer-scope-flag
git_commit_date 1784319759 1784398608
git_commit_sha b82b440 712b775
See matching parameters
Baseline Candidate
ci_job_date 1784399645 1784399645
ci_job_id 1871918205 1871918205
ci_pipeline_id 125482553 125482553
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
jdkVersion 11.0.25 11.0.25
jmhVersion 1.36 1.36
jvm /usr/lib/jvm/java-11-openjdk-amd64/bin/java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
jvmArgs -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/go/src/github.com/DataDog/apm-reliability/dd-trace-java/platform/src/producer-benchmark/build/tmp/jmh -Duser.country=US -Duser.language=en -Duser.variant -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/go/src/github.com/DataDog/apm-reliability/dd-trace-java/platform/src/producer-benchmark/build/tmp/jmh -Duser.country=US -Duser.language=en -Duser.variant
vmName OpenJDK 64-Bit Server VM OpenJDK 64-Bit Server VM
vmVersion 11.0.25+9-post-Ubuntu-1ubuntu122.04 11.0.25+9-post-Ubuntu-1ubuntu122.04

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 3 metrics, 0 unstable metrics.

See unchanged results
scenario Δ mean throughput
scenario:not-instrumented/KafkaProduceBenchmark.benchProduce same
scenario:only-tracing-dsm-disabled-benchmarks/KafkaProduceBenchmark.benchProduce same
scenario:only-tracing-dsm-enabled-benchmarks/KafkaProduceBenchmark.benchProduce same

@pr-commenter

pr-commenter Bot commented Jul 18, 2026

Copy link
Copy Markdown

Kafka / consumer-benchmark

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master brian.marks/kafka-create-consumer-scope-flag
git_commit_date 1784319759 1784398608
git_commit_sha b82b440 712b775
See matching parameters
Baseline Candidate
ci_job_date 1784399744 1784399744
ci_job_id 1871918206 1871918206
ci_pipeline_id 125482553 125482553
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
jdkVersion 11.0.25 11.0.25
jmhVersion 1.36 1.36
jvm /usr/lib/jvm/java-11-openjdk-amd64/bin/java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
jvmArgs -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/go/src/github.com/DataDog/apm-reliability/dd-trace-java/platform/src/consumer-benchmark/build/tmp/jmh -Duser.country=US -Duser.language=en -Duser.variant -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/go/src/github.com/DataDog/apm-reliability/dd-trace-java/platform/src/consumer-benchmark/build/tmp/jmh -Duser.country=US -Duser.language=en -Duser.variant
vmName OpenJDK 64-Bit Server VM OpenJDK 64-Bit Server VM
vmVersion 11.0.25+9-post-Ubuntu-1ubuntu122.04 11.0.25+9-post-Ubuntu-1ubuntu122.04

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 3 metrics, 0 unstable metrics.

See unchanged results
scenario Δ mean throughput
scenario:not-instrumented/KafkaConsumerBenchmark.benchConsume same
scenario:only-tracing-dsm-disabled-benchmarks/KafkaConsumerBenchmark.benchConsume unsure
[+1334.747op/s; +11762.764op/s] or [+0.446%; +3.931%]
scenario:only-tracing-dsm-enabled-benchmarks/KafkaConsumerBenchmark.benchConsume unsure
[-11706.835op/s; -1853.359op/s] or [-6.039%; -0.956%]

@bm1549 bm1549 changed the title Add DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED for Kafka consumers [WIP - DO NOT REVIEW] Add DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED for Kafka consumers Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

inst: kafka Kafka instrumentation tag: ai generated Largely based on code generated by an AI or LLM type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant