From 4d164529d950668fd41b0164b3101ccd57096c9e Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Mon, 12 Jan 2026 10:51:41 +0100 Subject: [PATCH] Automatically use SentryOptions.Metrics.BeforeSendMetricCallback Spring beans --- .../samples/spring7/web/MetricController.java | 4 ++-- .../io/sentry/systemtest/MetricsSystemTest.kt | 2 +- .../spring/jakarta/web/MetricController.java | 4 ++-- .../io/sentry/systemtest/MetricsSystemTest.kt | 2 +- .../samples/spring/web/MetricController.java | 4 ++-- .../io/sentry/systemtest/MetricsSystemTest.kt | 2 +- .../spring/boot4/SentryAutoConfiguration.java | 4 ++++ .../boot4/SentryAutoConfigurationTest.kt | 22 +++++++++++++++++++ .../boot/jakarta/SentryAutoConfiguration.java | 4 ++++ .../jakarta/SentryAutoConfigurationTest.kt | 22 +++++++++++++++++++ .../spring/boot/SentryAutoConfiguration.java | 4 ++++ .../boot/SentryAutoConfigurationTest.kt | 22 +++++++++++++++++++ 12 files changed, 87 insertions(+), 9 deletions(-) diff --git a/sentry-samples/sentry-samples-spring-7/src/main/java/io/sentry/samples/spring7/web/MetricController.java b/sentry-samples/sentry-samples-spring-7/src/main/java/io/sentry/samples/spring7/web/MetricController.java index cc8386fde24..d29fc1a89a3 100644 --- a/sentry-samples/sentry-samples-spring-7/src/main/java/io/sentry/samples/spring7/web/MetricController.java +++ b/sentry-samples/sentry-samples-spring-7/src/main/java/io/sentry/samples/spring7/web/MetricController.java @@ -20,13 +20,13 @@ String count() { } @GetMapping("gauge/{count}") - String gauge(@PathVariable Long count) { + String gauge(@PathVariable("count") Long count) { Sentry.metrics().gauge("memory.free", count.doubleValue(), "byte"); return "gauge metric tracked"; } @GetMapping("distribution/{count}") - String distribution(@PathVariable Long count) { + String distribution(@PathVariable("count") Long count) { Sentry.metrics().distribution("distributionMetric", count.doubleValue(), "child"); return "distribution metric tracked"; } diff --git a/sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt b/sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt index a379681adb3..9c9bb8baa8a 100644 --- a/sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt +++ b/sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt @@ -10,7 +10,7 @@ class MetricsSystemTest { @Before fun setup() { - testHelper = TestHelper("http://localhost:8080") + testHelper = TestHelper("http://localhost:8080/sentry-samples-spring-7-0.0.1-SNAPSHOT") testHelper.reset() } diff --git a/sentry-samples/sentry-samples-spring-jakarta/src/main/java/io/sentry/samples/spring/jakarta/web/MetricController.java b/sentry-samples/sentry-samples-spring-jakarta/src/main/java/io/sentry/samples/spring/jakarta/web/MetricController.java index f2e609b0f88..fb1526fb8ae 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/src/main/java/io/sentry/samples/spring/jakarta/web/MetricController.java +++ b/sentry-samples/sentry-samples-spring-jakarta/src/main/java/io/sentry/samples/spring/jakarta/web/MetricController.java @@ -20,13 +20,13 @@ String count() { } @GetMapping("gauge/{count}") - String gauge(@PathVariable Long count) { + String gauge(@PathVariable("count") Long count) { Sentry.metrics().gauge("memory.free", count.doubleValue(), "byte"); return "gauge metric tracked"; } @GetMapping("distribution/{count}") - String distribution(@PathVariable Long count) { + String distribution(@PathVariable("count") Long count) { Sentry.metrics().distribution("distributionMetric", count.doubleValue(), "child"); return "distribution metric tracked"; } diff --git a/sentry-samples/sentry-samples-spring-jakarta/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt b/sentry-samples/sentry-samples-spring-jakarta/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt index a379681adb3..6450307e222 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt +++ b/sentry-samples/sentry-samples-spring-jakarta/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt @@ -10,7 +10,7 @@ class MetricsSystemTest { @Before fun setup() { - testHelper = TestHelper("http://localhost:8080") + testHelper = TestHelper("http://localhost:8080/sentry-samples-spring-jakarta-0.0.1-SNAPSHOT") testHelper.reset() } diff --git a/sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/MetricController.java b/sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/MetricController.java index b425f973a69..82ca41b73cd 100644 --- a/sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/MetricController.java +++ b/sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/MetricController.java @@ -20,13 +20,13 @@ String count() { } @GetMapping("gauge/{count}") - String gauge(@PathVariable Long count) { + String gauge(@PathVariable("count") Long count) { Sentry.metrics().gauge("memory.free", count.doubleValue(), "byte"); return "gauge metric tracked"; } @GetMapping("distribution/{count}") - String distribution(@PathVariable Long count) { + String distribution(@PathVariable("count") Long count) { Sentry.metrics().distribution("distributionMetric", count.doubleValue(), "child"); return "distribution metric tracked"; } diff --git a/sentry-samples/sentry-samples-spring/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt b/sentry-samples/sentry-samples-spring/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt index a379681adb3..3a4b586b4f7 100644 --- a/sentry-samples/sentry-samples-spring/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt +++ b/sentry-samples/sentry-samples-spring/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt @@ -10,7 +10,7 @@ class MetricsSystemTest { @Before fun setup() { - testHelper = TestHelper("http://localhost:8080") + testHelper = TestHelper("http://localhost:8080/sentry-samples-spring-0.0.1-SNAPSHOT") testHelper.reset() } diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryAutoConfiguration.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryAutoConfiguration.java index 618895e51fe..1b804e8cb8d 100644 --- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryAutoConfiguration.java +++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryAutoConfiguration.java @@ -105,6 +105,8 @@ static class HubConfiguration { beforeSendTransactionCallback, final @NotNull ObjectProvider beforeSendLogsCallback, + final @NotNull ObjectProvider + beforeSendMetricCallback, final @NotNull ObjectProvider beforeBreadcrumbCallback, final @NotNull ObjectProvider tracesSamplerCallback, @@ -117,6 +119,8 @@ static class HubConfiguration { beforeSendCallback.ifAvailable(options::setBeforeSend); beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction); beforeSendLogsCallback.ifAvailable(callback -> options.getLogs().setBeforeSend(callback)); + beforeSendMetricCallback.ifAvailable( + callback -> options.getMetrics().setBeforeSend(callback)); beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb); tracesSamplerCallback.ifAvailable(options::setTracesSampler); eventProcessors.forEach(options::addEventProcessor); diff --git a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt index 14a79a761f9..51bbb8d83d1 100644 --- a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/SentryAutoConfigurationTest.kt @@ -21,6 +21,7 @@ import io.sentry.SentryEvent import io.sentry.SentryIntegrationPackageStorage import io.sentry.SentryLevel import io.sentry.SentryLogEvent +import io.sentry.SentryMetricsEvent import io.sentry.SentryOptions import io.sentry.asyncprofiler.profiling.JavaContinuousProfiler import io.sentry.asyncprofiler.provider.AsyncProfilerProfileConverterProvider @@ -370,6 +371,17 @@ class SentryAutoConfigurationTest { } } + @Test + fun `registers metrics beforeSendCallback on SentryOptions`() { + contextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration(CustomBeforeSendMetricCallbackConfiguration::class.java) + .run { + assertThat(it.getBean(SentryOptions::class.java).metrics.beforeSend) + .isInstanceOf(CustomBeforeSendMetricCallback::class.java) + } + } + @Test fun `registers beforeBreadcrumbCallback on SentryOptions`() { contextRunner @@ -1240,6 +1252,16 @@ class SentryAutoConfigurationTest { override fun execute(event: SentryLogEvent): SentryLogEvent? = null } + @Configuration(proxyBeanMethods = false) + open class CustomBeforeSendMetricCallbackConfiguration { + + @Bean open fun beforeSendCallback() = CustomBeforeSendMetricCallback() + } + + class CustomBeforeSendMetricCallback : SentryOptions.Metrics.BeforeSendMetricCallback { + override fun execute(metric: SentryMetricsEvent, hint: Hint): SentryMetricsEvent? = null + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendTransactionCallbackConfiguration { 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 9ae80432eed..8663dac8c56 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 @@ -105,6 +105,8 @@ static class HubConfiguration { beforeSendTransactionCallback, final @NotNull ObjectProvider beforeSendLogsCallback, + final @NotNull ObjectProvider + beforeSendMetricCallback, final @NotNull ObjectProvider beforeBreadcrumbCallback, final @NotNull ObjectProvider onDiscardCallback, @@ -118,6 +120,8 @@ static class HubConfiguration { beforeSendCallback.ifAvailable(options::setBeforeSend); beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction); beforeSendLogsCallback.ifAvailable(callback -> options.getLogs().setBeforeSend(callback)); + beforeSendMetricCallback.ifAvailable( + callback -> options.getMetrics().setBeforeSend(callback)); beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb); onDiscardCallback.ifAvailable(options::setOnDiscard); tracesSamplerCallback.ifAvailable(options::setTracesSampler); diff --git a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt index 7dadbf60249..72ed7b8d8ba 100644 --- a/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt @@ -23,6 +23,7 @@ import io.sentry.SentryEvent import io.sentry.SentryIntegrationPackageStorage import io.sentry.SentryLevel import io.sentry.SentryLogEvent +import io.sentry.SentryMetricsEvent import io.sentry.SentryOptions import io.sentry.asyncprofiler.profiling.JavaContinuousProfiler import io.sentry.asyncprofiler.provider.AsyncProfilerProfileConverterProvider @@ -381,6 +382,17 @@ class SentryAutoConfigurationTest { } } + @Test + fun `registers metrics beforeSendCallback on SentryOptions`() { + contextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration(CustomBeforeSendMetricCallbackConfiguration::class.java) + .run { + assertThat(it.getBean(SentryOptions::class.java).metrics.beforeSend) + .isInstanceOf(CustomBeforeSendMetricCallback::class.java) + } + } + @Test fun `registers beforeBreadcrumbCallback on SentryOptions`() { contextRunner @@ -1262,6 +1274,16 @@ class SentryAutoConfigurationTest { override fun execute(event: SentryLogEvent): SentryLogEvent? = null } + @Configuration(proxyBeanMethods = false) + open class CustomBeforeSendMetricCallbackConfiguration { + + @Bean open fun beforeSendCallback() = CustomBeforeSendMetricCallback() + } + + class CustomBeforeSendMetricCallback : SentryOptions.Metrics.BeforeSendMetricCallback { + override fun execute(metric: SentryMetricsEvent, hint: Hint): SentryMetricsEvent? = null + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendTransactionCallbackConfiguration { diff --git a/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java b/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java index ec7998eaa88..76424b5c55f 100644 --- a/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java +++ b/sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java @@ -103,6 +103,8 @@ static class HubConfiguration { beforeSendTransactionCallback, final @NotNull ObjectProvider beforeSendLogsCallback, + final @NotNull ObjectProvider + beforeSendMetricCallback, final @NotNull ObjectProvider beforeBreadcrumbCallback, final @NotNull ObjectProvider onDiscardCallback, @@ -116,6 +118,8 @@ static class HubConfiguration { beforeSendCallback.ifAvailable(options::setBeforeSend); beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction); beforeSendLogsCallback.ifAvailable(callback -> options.getLogs().setBeforeSend(callback)); + beforeSendMetricCallback.ifAvailable( + callback -> options.getMetrics().setBeforeSend(callback)); beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb); onDiscardCallback.ifAvailable(options::setOnDiscard); tracesSamplerCallback.ifAvailable(options::setTracesSampler); diff --git a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt index 00cd7f06b16..70cb61d088d 100644 --- a/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt @@ -23,6 +23,7 @@ import io.sentry.SentryEvent import io.sentry.SentryIntegrationPackageStorage import io.sentry.SentryLevel import io.sentry.SentryLogEvent +import io.sentry.SentryMetricsEvent import io.sentry.SentryOptions import io.sentry.asyncprofiler.profiling.JavaContinuousProfiler import io.sentry.asyncprofiler.provider.AsyncProfilerProfileConverterProvider @@ -369,6 +370,17 @@ class SentryAutoConfigurationTest { } } + @Test + fun `registers metrics beforeSendCallback on SentryOptions`() { + contextRunner + .withPropertyValues("sentry.dsn=http://key@localhost/proj") + .withUserConfiguration(CustomBeforeSendMetricCallbackConfiguration::class.java) + .run { + assertThat(it.getBean(SentryOptions::class.java).metrics.beforeSend) + .isInstanceOf(CustomBeforeSendMetricCallback::class.java) + } + } + @Test fun `registers beforeSendTransactionCallback on SentryOptions`() { contextRunner @@ -1188,6 +1200,16 @@ class SentryAutoConfigurationTest { override fun execute(event: SentryLogEvent): SentryLogEvent? = null } + @Configuration(proxyBeanMethods = false) + open class CustomBeforeSendMetricCallbackConfiguration { + + @Bean open fun beforeSendCallback() = CustomBeforeSendMetricCallback() + } + + class CustomBeforeSendMetricCallback : SentryOptions.Metrics.BeforeSendMetricCallback { + override fun execute(metric: SentryMetricsEvent, hint: Hint): SentryMetricsEvent? = null + } + @Configuration(proxyBeanMethods = false) open class CustomBeforeSendTransactionCallbackConfiguration {