ref(kafka): [Queue Instrumentation 14] Extract sentry-kafka module#5288
ref(kafka): [Queue Instrumentation 14] Extract sentry-kafka module#5288adinauer wants to merge 2 commits intofix/queue-instrumentation-enqueued-time-secondsfrom
Conversation
Move Kafka producer interceptor to a new sentry-kafka module and rename to SentryKafkaProducerInterceptor. Add SentryKafkaConsumerInterceptor for vanilla kafka-clients users. Spring integration now depends on sentry-kafka and passes a Spring-specific trace origin. This allows non-Spring applications to use Kafka queue instrumentation directly via kafka-clients interceptor config. Co-Authored-By: Claude <noreply@anthropic.com>
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨Spring Jakarta
Other
Internal Changes 🔧Deps
Other
🤖 This preview updates automatically when you update the PR. |
Sentry Build Distribution
|
Performance metrics 🚀
|
| public final class SentryKafkaConsumerInterceptor<K, V> implements ConsumerInterceptor<K, V> { | ||
|
|
||
| public static final @NotNull String TRACE_ORIGIN = "auto.queue.kafka.consumer"; | ||
|
|
||
| private final @NotNull IScopes scopes; | ||
|
|
||
| public SentryKafkaConsumerInterceptor(final @NotNull IScopes scopes) { | ||
| this.scopes = scopes; | ||
| } |
There was a problem hiding this comment.
Bug: SentryKafkaConsumerInterceptor and SentryKafkaProducerInterceptor lack public no-arg constructors, preventing instantiation by Kafka when configured via class name.
Severity: HIGH
Suggested Fix
Add a public, no-argument constructor to both SentryKafkaConsumerInterceptor and SentryKafkaProducerInterceptor. The required IScopes dependency could then be injected via the configure() method, which Kafka calls after instantiation.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerInterceptor.java#L26-L34
Potential issue: The `SentryKafkaConsumerInterceptor` and
`SentryKafkaProducerInterceptor` classes only have constructors that require an
`IScopes` parameter. However, when these interceptors are configured in a non-Spring
application using the standard Kafka `interceptor.classes` property, Kafka's client
library attempts to instantiate them using reflection, which requires a public
no-argument constructor. The absence of this constructor will cause an
`InstantiationException` at producer or consumer startup, preventing the interceptors
from being used as intended in non-Spring environments.
Did we get this right? 👍 / 👎 to inform future reviews.
| transaction.setData("messaging.batch.message.count", records.count()); | ||
| transaction.setStatus(SpanStatus.OK); | ||
| transaction.finish(); |
There was a problem hiding this comment.
Bug: The transaction in SentryKafkaConsumerInterceptor finishes immediately with a hardcoded OK status and is not bound to the scope, failing to measure actual message processing.
Severity: MEDIUM
Suggested Fix
Instead of creating and finishing a transaction, consider starting a transaction and binding it to the scope. This would allow user code to retrieve the active span and finish it after message processing is complete, accurately capturing its duration and status. Document this pattern for non-Spring users.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location:
sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerInterceptor.java#L59-L61
Potential issue: In `SentryKafkaConsumerInterceptor`, a transaction is created and
finished within the `onConsume` method itself. It is explicitly not bound to the scope
(`setBindToScope(false)`) and is always marked with `SpanStatus.OK`. This means the
transaction only measures the interceptor's execution time (microseconds) and does not
capture the duration or result of the actual message processing, providing limited
observability value.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0734938. Configure here.
|
|
||
| dependencies { | ||
| api(projects.sentry) | ||
| compileOnly(projects.sentryKafka) |
There was a problem hiding this comment.
Missing sentry-kafka runtime dependency causes NoClassDefFoundError
High Severity
sentry-kafka is declared as compileOnly in sentry-spring-jakarta, so it's not on the runtime classpath for consumers. However, SentryKafkaProducerBeanPostProcessor and SentryKafkaRecordInterceptor directly reference SentryKafkaProducerInterceptor from sentry-kafka. The auto-configuration's @ConditionalOnClass(KafkaTemplate.class) only checks for Spring Kafka, not for any sentry-kafka class. This will cause a NoClassDefFoundError for Spring Boot users who have spring-kafka and enable queue tracing but don't explicitly add sentry-kafka. Other optional modules (GraphQL, Quartz) include their Sentry module classes in their @ConditionalOnClass checks, but Kafka does not.
Reviewed by Cursor Bugbot for commit 0734938. Configure here.


PR Stack (Queue Instrumentation)
📜 Description
Extract Kafka interceptors into a standalone
sentry-kafkamodule so that non-Spring applications usingkafka-clientsdirectly can get queue instrumentation.SentryProducerInterceptor→SentryKafkaProducerInterceptorinsentry-kafkaSentryKafkaConsumerInterceptorfor vanilla Kafka consumers (createsqueue.receivetransactions with trace propagation)sentry-spring-jakartanow depends onsentry-kafkaand passes a Spring-specific trace originauto.queue.kafka.producerandauto.queue.kafka.consumerspan origins💡 Motivation and Context
The Kafka queue instrumentation was previously only available through the Spring integration. Plain
kafka-clientsusers had no way to use it. This extraction makes the interceptors reusable outside Spring via standard Kafka interceptor configuration.💚 How did you test it?
SentryKafkaConsumerInterceptorandSentryKafkaProducerInterceptorin the new module📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps