Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 3, 2025

Add Configurable OpenTelemetry Kafka Client Interceptors

Added new configurable kafka-clients interceptors that use KafkaTelemetry instances instead of GlobalOpenTelemetry, following a similar pattern to OpenTelemetryMetricsReporter.

Problem Statement

  • TracingConsumerInterceptor and TracingProducerInterceptor used GlobalOpenTelemetry.get() as static fields
  • Interceptors were not configurable - users had no control over the OpenTelemetry instance or settings

Solution Implemented

Created new interceptor classes with programmatic configuration:

  1. New OpenTelemetryProducerInterceptor and OpenTelemetryConsumerInterceptor with full programmatic configuration
  2. Use KafkaTelemetrySupplier to pass exact KafkaTelemetry instances configured by users
  3. No system property checks - configuration is purely programmatic
  4. Old TracingProducerInterceptor and TracingConsumerInterceptor marked as deprecated but kept unchanged for backwards compatibility

Changes Made

  • Created OpenTelemetryProducerInterceptor and OpenTelemetryConsumerInterceptor (recommended)
  • Created KafkaTelemetrySupplier for passing KafkaTelemetry instances through Kafka config
  • Added producerInterceptorConfigProperties() and consumerInterceptorConfigProperties() to KafkaTelemetry
  • Deprecated old Tracing* interceptors with simple deprecation messages
  • Added comprehensive tests (KafkaTelemetryInterceptorTest)
  • Updated README with usage examples

Benefits

  • Fully configurable with all KafkaTelemetry builder options preserved
  • Better naming reflecting they're not limited to tracing
  • Backwards compatible - old interceptors still work
  • Clear migration path via deprecation notices

Fixes #6291

Original prompt

This section details on the original issue you should resolve

<issue_title>Refactor existing kafka-clients interceptors in library instrumentation</issue_title>
<issue_description>Is your feature request related to a problem? Please describe.
Currently the interceptors are not configurable in any way, and they use the global OpenTelemetry.

Describe the solution you'd like
We could use the same pattern as in the kafka metrics PR: #6138

Additional context
#6264 (comment)
</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #6291

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Refactor existing kafka-clients interceptors in library instrumentation Refactor kafka-clients interceptors to be configurable Oct 3, 2025
@Copilot Copilot AI requested a review from trask October 3, 2025 01:41
Copilot finished work on behalf of trask October 3, 2025 01:41
Copy link
Contributor Author

Copilot AI commented Oct 3, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • scans-in.gradle.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/gradle-daemon-main-9.1.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/agents/gradle-instrumentation-agent-9.1.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.1.0 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Copilot Copilot AI requested a review from trask October 3, 2025 02:51
Copilot finished work on behalf of trask October 3, 2025 02:51
Copy link
Contributor Author

Copilot AI commented Oct 3, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • scans-in.gradle.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/gradle-daemon-main-9.1.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/agents/gradle-instrumentation-agent-9.1.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.1.0 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of trask October 3, 2025 03:24
Copy link
Contributor Author

Copilot AI commented Oct 3, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • scans-in.gradle.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/gradle-daemon-main-9.1.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/agents/gradle-instrumentation-agent-9.1.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.1.0 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of trask October 3, 2025 03:52
@Copilot Copilot AI requested a review from trask October 3, 2025 03:52
@Copilot Copilot AI requested a review from trask October 3, 2025 04:17
Copilot finished work on behalf of trask October 3, 2025 17:24
@otelbot-java-instrumentation
Copy link
Contributor

🔧 The result from spotlessApply was committed to the PR branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot looks like this class is only used in kafka-client-2.6:library module? if so can we move it there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved KafkaTelemetrySupplier from kafka-clients-common-0.11/library/...internal/ to kafka-clients-2.6/library/.../v2_6/internal/ since it's only used in the kafka-clients-2.6 module.

…wards compatibility, move KafkaTelemetrySupplier

Co-authored-by: trask <[email protected]>
Copy link
Contributor Author

Copilot AI commented Oct 8, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • scans-in.gradle.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/gradle-daemon-main-9.1.0.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-9.1.0-bin/9agqghryom9wkf8r80qlhnts3/gradle-9.1.0/lib/agents/gradle-instrumentation-agent-9.1.0.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 9.1.0 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Copilot Copilot AI changed the title Refactor kafka-clients interceptors to be configurable Add configurable OpenTelemetry kafka-clients interceptors Oct 8, 2025
@Copilot Copilot AI requested a review from trask October 8, 2025 03:51
Copilot finished work on behalf of trask October 8, 2025 03:51
*
* @see KafkaTelemetry#consumerInterceptorConfigProperties()
*/
public class OpenTelemetryConsumerInterceptor<K, V> implements ConsumerInterceptor<K, V> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot mark TracingConsumerIntercepter and TracingProducerInterceptor as deprecated and recommend to use these new classes instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked both TracingConsumerInterceptor and TracingProducerInterceptor as @Deprecated with javadoc comments recommending the new OpenTelemetry* classes. See commit [pending].

Copilot finished work on behalf of trask October 8, 2025 14:35
@Copilot Copilot AI requested a review from trask October 8, 2025 14:35
Copilot finished work on behalf of trask October 8, 2025 15:33
@Copilot Copilot AI requested a review from trask October 8, 2025 15:33
…src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingConsumerInterceptor.java
…src/main/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/TracingProducerInterceptor.java
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot make a copy of this named AbstractDeprecatedInterceptorsTest

and that class should be the same as this class used to be (testing the now deprecated interceptors)

and create copies of the subclasses OldInterceptorsTest and OldInterceptorsSuppressReceiveSpansTest and have those extend AbstractOldInterceptorsTest

Copilot finished work on behalf of trask October 8, 2025 23:41
@Copilot Copilot AI requested a review from trask October 8, 2025 23:41
The interceptor class has to be set in the properties bag used to create the Kafka client.

Use the `TracingProducerInterceptor` for the producer in order to create a "send" span automatically, each time a message is sent.
##### Recommended approach: Configuring interceptors with KafkaTelemetry
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot update the doc, only need to mention the new approach, no need to mention the now deprecated approach (Alternative: Using interceptors with global OpenTelemetry)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor existing kafka-clients interceptors in library instrumentation
2 participants