From ce2ea96545426d2a5ea42d5b77167b8c07da186d Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 7 Apr 2026 12:35:14 +0200 Subject: [PATCH 1/2] fix(spring-boot-jakarta): Disable Sentry Kafka instrumentation when OTel is active Skip registration of SentryKafkaProducerBeanPostProcessor and SentryKafkaConsumerBeanPostProcessor when a Sentry OpenTelemetry integration (agent or agentless) is on the classpath. OpenTelemetry provides its own Kafka instrumentation, so Sentry's would create duplicate spans. --- .../boot/jakarta/SentryAutoConfiguration.java | 1 + .../SentryKafkaAutoConfigurationTest.kt | 32 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java index 71b5f97ed1..0499df95b1 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java @@ -252,6 +252,7 @@ static class SentryCacheConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(KafkaTemplate.class) @ConditionalOnProperty(name = "sentry.enable-queue-tracing", havingValue = "true") + @ConditionalOnMissingClass("io.sentry.opentelemetry.SentryAutoConfigurationCustomizerProvider") @Open static class SentryKafkaQueueConfiguration { diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryKafkaAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryKafkaAutoConfigurationTest.kt index 2d96fbf917..c0963580f3 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryKafkaAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryKafkaAutoConfigurationTest.kt @@ -1,10 +1,12 @@ package io.sentry.spring.boot.jakarta +import io.sentry.opentelemetry.SentryAutoConfigurationCustomizerProvider import io.sentry.spring.jakarta.kafka.SentryKafkaConsumerBeanPostProcessor import io.sentry.spring.jakarta.kafka.SentryKafkaProducerBeanPostProcessor import kotlin.test.Test import org.assertj.core.api.Assertions.assertThat import org.springframework.boot.autoconfigure.AutoConfigurations +import org.springframework.boot.test.context.FilteredClassLoader import org.springframework.boot.test.context.runner.ApplicationContextRunner class SentryKafkaAutoConfigurationTest { @@ -24,17 +26,24 @@ class SentryKafkaAutoConfigurationTest { "sentry.debug=false", ) + /** Hide the OTel customizer so conditions evaluate as "no OTel present". */ + private val noOtelClassLoader = + FilteredClassLoader(SentryAutoConfigurationCustomizerProvider::class.java) + @Test fun `registers Kafka BPPs when queue tracing is enabled`() { - contextRunner.withPropertyValues("sentry.enable-queue-tracing=true").run { context -> - assertThat(context).hasSingleBean(SentryKafkaProducerBeanPostProcessor::class.java) - assertThat(context).hasSingleBean(SentryKafkaConsumerBeanPostProcessor::class.java) - } + contextRunner + .withClassLoader(noOtelClassLoader) + .withPropertyValues("sentry.enable-queue-tracing=true") + .run { context -> + assertThat(context).hasSingleBean(SentryKafkaProducerBeanPostProcessor::class.java) + assertThat(context).hasSingleBean(SentryKafkaConsumerBeanPostProcessor::class.java) + } } @Test fun `does not register Kafka BPPs when queue tracing is disabled`() { - contextRunner.run { context -> + contextRunner.withClassLoader(noOtelClassLoader).run { context -> assertThat(context).doesNotHaveBean(SentryKafkaProducerBeanPostProcessor::class.java) assertThat(context).doesNotHaveBean(SentryKafkaConsumerBeanPostProcessor::class.java) } @@ -42,7 +51,18 @@ class SentryKafkaAutoConfigurationTest { @Test fun `does not register Kafka BPPs when queue tracing is explicitly false`() { - contextRunner.withPropertyValues("sentry.enable-queue-tracing=false").run { context -> + contextRunner + .withClassLoader(noOtelClassLoader) + .withPropertyValues("sentry.enable-queue-tracing=false") + .run { context -> + assertThat(context).doesNotHaveBean(SentryKafkaProducerBeanPostProcessor::class.java) + assertThat(context).doesNotHaveBean(SentryKafkaConsumerBeanPostProcessor::class.java) + } + } + + @Test + fun `does not register Kafka BPPs when OpenTelemetry integration is present`() { + contextRunner.withPropertyValues("sentry.enable-queue-tracing=true").run { context -> assertThat(context).doesNotHaveBean(SentryKafkaProducerBeanPostProcessor::class.java) assertThat(context).doesNotHaveBean(SentryKafkaConsumerBeanPostProcessor::class.java) } From 414b118b605225bf553415a4b0875c6124cee5f7 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 7 Apr 2026 12:46:11 +0200 Subject: [PATCH 2/2] fix(core): Add Kafka span origins to ignored list for OpenTelemetry Add auto.queue.spring_jakarta.kafka.producer and auto.queue.spring_jakarta.kafka.consumer to the ignored span origins when running with OTel agent or agentless-spring. Prevents duplicate spans when both Sentry and OTel Kafka instrumentation are active. --- sentry/src/main/java/io/sentry/util/SpanUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry/src/main/java/io/sentry/util/SpanUtils.java b/sentry/src/main/java/io/sentry/util/SpanUtils.java index cad4d48365..7f21422ba6 100644 --- a/sentry/src/main/java/io/sentry/util/SpanUtils.java +++ b/sentry/src/main/java/io/sentry/util/SpanUtils.java @@ -40,6 +40,8 @@ public final class SpanUtils { origins.add("auto.http.spring7.resttemplate"); origins.add("auto.http.openfeign"); origins.add("auto.http.ktor-client"); + origins.add("auto.queue.spring_jakarta.kafka.producer"); + origins.add("auto.queue.spring_jakarta.kafka.consumer"); } if (SentryOpenTelemetryMode.AGENT == mode) {