From 61f485a949ca7cceaf65301f981430f9b7a63040 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 13 Aug 2026 06:16:48 +0200 Subject: [PATCH] feat(spring): Warn for legacy Metrics property Inspect the Spring Environment before SDK initialization and emit tailored migration warnings for explicit sentry.metrics.enabled values without binding or applying the obsolete property. Co-Authored-By: Claude --- .../spring/boot4/SentryAutoConfiguration.java | 24 ++++++++++ .../boot4/SentryAutoConfigurationTest.kt | 46 +++++++++++++++++++ .../boot/jakarta/SentryAutoConfiguration.java | 24 ++++++++++ .../jakarta/SentryAutoConfigurationTest.kt | 46 +++++++++++++++++++ .../spring/boot/SentryAutoConfiguration.java | 24 ++++++++++ .../boot/SentryAutoConfigurationTest.kt | 46 +++++++++++++++++++ 6 files changed, 210 insertions(+) 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 17be277750..d118250f34 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 @@ -187,6 +187,7 @@ static class OpenTelemetryNoAgentConfiguration {} // here we make sure that only classes that extend throwable are set on this field options.getIgnoredExceptionsForType().removeIf(it -> !Throwable.class.isAssignableFrom(it)); warnForLegacyLogsConfiguration(environment, options); + warnForLegacyMetricsConfiguration(environment, options); Sentry.init(options); return ScopesAdapter.getInstance(); } @@ -216,6 +217,29 @@ private void warnForLegacyLogsConfiguration( } } + private void warnForLegacyMetricsConfiguration( + final @NotNull Environment environment, final @NotNull SentryOptions options) { + if (environment.containsProperty("sentry.metrics.enabled")) { + final boolean enableMetrics = + Boolean.TRUE.equals(environment.getProperty("sentry.metrics.enabled", Boolean.class)); + if (enableMetrics) { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it."); + } else { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls."); + } + } + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(MDC.class) @Open 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 c3a7556e3e..5aabbdef92 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 @@ -247,6 +247,52 @@ class SentryAutoConfigurationTest { } } + @Test + fun `legacy metrics property emits no warning when absent`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { verify(logger, never()).log(eq(SentryLevel.WARNING), any()) } + } + + @Test + fun `legacy metrics property true emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it.", + *emptyArray(), + ) + } + } + + @Test + fun `legacy metrics property false emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=false") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls.", + *emptyArray(), + ) + } + } + @Test fun `properties are applied to SentryOptions`() { contextRunner 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 ec79b61e12..86ef72a48f 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 @@ -189,6 +189,7 @@ static class OpenTelemetryNoAgentConfiguration {} // here we make sure that only classes that extend throwable are set on this field options.getIgnoredExceptionsForType().removeIf(it -> !Throwable.class.isAssignableFrom(it)); warnForLegacyLogsConfiguration(environment, options); + warnForLegacyMetricsConfiguration(environment, options); Sentry.init(options); return ScopesAdapter.getInstance(); } @@ -218,6 +219,29 @@ private void warnForLegacyLogsConfiguration( } } + private void warnForLegacyMetricsConfiguration( + final @NotNull Environment environment, final @NotNull SentryOptions options) { + if (environment.containsProperty("sentry.metrics.enabled")) { + final boolean enableMetrics = + Boolean.TRUE.equals(environment.getProperty("sentry.metrics.enabled", Boolean.class)); + if (enableMetrics) { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it."); + } else { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls."); + } + } + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(MDC.class) @Open 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 1ce6c8071e..df99445940 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 @@ -250,6 +250,52 @@ class SentryAutoConfigurationTest { } } + @Test + fun `legacy metrics property emits no warning when absent`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { verify(logger, never()).log(eq(SentryLevel.WARNING), any()) } + } + + @Test + fun `legacy metrics property true emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it.", + *emptyArray(), + ) + } + } + + @Test + fun `legacy metrics property false emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=false") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls.", + *emptyArray(), + ) + } + } + @Test fun `properties are applied to SentryOptions`() { contextRunner 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 bedb72a19e..83d342de52 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 @@ -184,6 +184,7 @@ static class OpenTelemetryNoAgentConfiguration {} // here we make sure that only classes that extend throwable are set on this field options.getIgnoredExceptionsForType().removeIf(it -> !Throwable.class.isAssignableFrom(it)); warnForLegacyLogsConfiguration(environment, options); + warnForLegacyMetricsConfiguration(environment, options); Sentry.init(options); return ScopesAdapter.getInstance(); } @@ -213,6 +214,29 @@ private void warnForLegacyLogsConfiguration( } } + private void warnForLegacyMetricsConfiguration( + final @NotNull Environment environment, final @NotNull SentryOptions options) { + if (environment.containsProperty("sentry.metrics.enabled")) { + final boolean enableMetrics = + Boolean.TRUE.equals(environment.getProperty("sentry.metrics.enabled", Boolean.class)); + if (enableMetrics) { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it."); + } else { + options + .getLogger() + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls."); + } + } + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(MDC.class) @Open 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 b0ee03d657..2315a616d2 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 @@ -248,6 +248,52 @@ class SentryAutoConfigurationTest { } } + @Test + fun `legacy metrics property emits no warning when absent`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { verify(logger, never()).log(eq(SentryLevel.WARNING), any()) } + } + + @Test + fun `legacy metrics property true emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=true") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property is no longer supported. Manual " + + "Sentry.metrics() calls no longer require it.", + *emptyArray(), + ) + } + } + + @Test + fun `legacy metrics property false emits migration warning`() { + val logger = mock() + dsnEnabledRunner + .withPropertyValues("sentry.debug=true", "sentry.metrics.enabled=false") + .withBean(ILogger::class.java, { logger }) + .withUserConfiguration(LoggerConfiguration::class.java) + .run { + verify(logger) + .log( + SentryLevel.WARNING, + "The 'sentry.metrics.enabled' property no longer disables manual " + + "Sentry.metrics() calls.", + *emptyArray(), + ) + } + } + @Test fun `properties are applied to SentryOptions`() { contextRunner