Skip to content

ref(kafka): [Queue Instrumentation 14] Extract sentry-kafka module#5288

Open
adinauer wants to merge 2 commits intofix/queue-instrumentation-enqueued-time-secondsfrom
feat/queue-instrumentation-kafka-module
Open

ref(kafka): [Queue Instrumentation 14] Extract sentry-kafka module#5288
adinauer wants to merge 2 commits intofix/queue-instrumentation-enqueued-time-secondsfrom
feat/queue-instrumentation-kafka-module

Conversation

@adinauer
Copy link
Copy Markdown
Member

@adinauer adinauer commented Apr 13, 2026

PR Stack (Queue Instrumentation)


📜 Description

Extract Kafka interceptors into a standalone sentry-kafka module so that non-Spring applications using kafka-clients directly can get queue instrumentation.

  • Move SentryProducerInterceptorSentryKafkaProducerInterceptor in sentry-kafka
  • Add SentryKafkaConsumerInterceptor for vanilla Kafka consumers (creates queue.receive transactions with trace propagation)
  • sentry-spring-jakarta now depends on sentry-kafka and passes a Spring-specific trace origin
  • Register new auto.queue.kafka.producer and auto.queue.kafka.consumer span origins

💡 Motivation and Context

The Kafka queue instrumentation was previously only available through the Spring integration. Plain kafka-clients users had no way to use it. This extraction makes the interceptors reusable outside Spring via standard Kafka interceptor configuration.

💚 How did you test it?

  • Unit tests for SentryKafkaConsumerInterceptor and SentryKafkaProducerInterceptor in the new module
  • Existing Spring Kafka tests updated to use the renamed classes

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

⚠️ Merge this PR using a merge commit (not squash). Only the collection branch is squash-merged into main.

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>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Spring Jakarta

  • [Queue Instrumentation 4] Add Kafka consumer instrumentation by adinauer in #5255
  • [Queue Instrumentation 3] Add Kafka producer instrumentation by adinauer in #5254

Other

  • (core) [Queue Instrumentation 1] Add enableQueueTracing option and messaging span data conventions by adinauer in #5250
  • (samples) [Queue Instrumentation 2] Add Kafka to Spring Boot 3 sample app by adinauer in #5253
  • (spring-boot-jakarta) [Queue Instrumentation 5] Add Kafka queue auto-configuration by adinauer in #5256
  • Add strict trace continuation support by giortzisg in #5136
  • Sync file attachments to native by bitsandfoxes in #5211

Internal Changes 🔧

Deps

  • Bump requests from 2.32.4 to 2.33.0 in the uv group across 1 directory by dependabot in #5237
  • Bump github/codeql-action from 4.32.6 to 4.35.1 by dependabot in #5243

Other

  • (kafka) [Queue Instrumentation 14] Extract sentry-kafka module by adinauer in #5288
  • (samples) [Queue Instrumentation 6] Add Kafka queue system tests by adinauer in #5260
  • Add THIRD_PARTY_NOTICES.md for vendored third-party code by markushi in #5186

🤖 This preview updates automatically when you update the PR.

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 13, 2026

Sentry Build Distribution

App Name App ID Version Configuration Install Page
SDK Size io.sentry.tests.size 8.37.1 (1) release Install Build

Configure sentry-android build distribution settings

@github-actions
Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 309.33 ms 348.62 ms 39.29 ms
Size 0 B 0 B 0 B

Baseline results on branch: fix/queue-instrumentation-enqueued-time-seconds

Startup times

Revision Plain With Sentry Diff
789996b 330.43 ms 392.48 ms 62.05 ms

App size

Revision Plain With Sentry Diff
789996b 0 B 0 B 0 B

Comment on lines +26 to +34
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;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Comment on lines +59 to +61
transaction.setData("messaging.batch.message.count", records.count());
transaction.setStatus(SpanStatus.OK);
transaction.finish();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0734938. Configure here.

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.

1 participant