From 1c87fcb8064f7f4b30ee9cf472f254b9d18aeeea Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 9 May 2023 11:21:34 +0200 Subject: [PATCH] Add property to disable DisableObservabilityContextCustomizer Closes gh-35009 --- ...ObservabilityContextCustomizerFactory.java | 44 ++++++++----- .../spring-configuration-metadata.json | 8 ++- ...vabilityContextCustomizerFactoryTests.java | 64 ++++++++++++++++++- 3 files changed, 98 insertions(+), 18 deletions(-) diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java index ab1791fb21..918777baf1 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java @@ -37,6 +37,7 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.core.Ordered; +import org.springframework.core.env.Environment; import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextCustomizer; import org.springframework.test.context.ContextCustomizerFactory; @@ -45,8 +46,9 @@ import org.springframework.test.context.TestContextAnnotationUtils; import org.springframework.util.ClassUtils; /** - * {@link ContextCustomizerFactory} that globally disables metrics export and tracing - * unless {@link AutoConfigureObservability} is set on the test class. + * {@link ContextCustomizerFactory} that globally disables metrics export and tracing in + * tests. The behaviour can be controlled with {@link AutoConfigureObservability} on the + * test class or via the {@value #AUTO_CONFIGURE_PROPERTY} property. *

* Registers {@link Tracer#NOOP} if tracing is disabled, micrometer-tracing is on the * classpath, and the user hasn't supplied their own {@link Tracer}. @@ -56,43 +58,53 @@ import org.springframework.util.ClassUtils; */ class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory { + static final String AUTO_CONFIGURE_PROPERTY = "spring.test.observability.auto-configure"; + @Override public ContextCustomizer createContextCustomizer(Class testClass, List configAttributes) { AutoConfigureObservability annotation = TestContextAnnotationUtils.findMergedAnnotation(testClass, AutoConfigureObservability.class); - if (annotation == null) { - return new DisableObservabilityContextCustomizer(true, true); - } - return new DisableObservabilityContextCustomizer(!annotation.metrics(), !annotation.tracing()); + return new DisableObservabilityContextCustomizer(annotation); } private static class DisableObservabilityContextCustomizer implements ContextCustomizer { - private final boolean disableMetrics; - - private final boolean disableTracing; + private final AutoConfigureObservability annotation; - DisableObservabilityContextCustomizer(boolean disableMetrics, boolean disableTracing) { - this.disableMetrics = disableMetrics; - this.disableTracing = disableTracing; + DisableObservabilityContextCustomizer(AutoConfigureObservability annotation) { + this.annotation = annotation; } @Override public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedContextConfiguration) { - if (this.disableMetrics) { + if (areMetricsDisabled(context.getEnvironment())) { TestPropertyValues .of("management.defaults.metrics.export.enabled=false", "management.simple.metrics.export.enabled=true") .applyTo(context); } - if (this.disableTracing) { + if (isTracingDisabled(context.getEnvironment())) { TestPropertyValues.of("management.tracing.enabled=false").applyTo(context); registerNoopTracer(context); } } + private boolean areMetricsDisabled(Environment environment) { + if (this.annotation != null) { + return !this.annotation.metrics(); + } + return !environment.getProperty(AUTO_CONFIGURE_PROPERTY, Boolean.class, false); + } + + private boolean isTracingDisabled(Environment environment) { + if (this.annotation != null) { + return !this.annotation.tracing(); + } + return !environment.getProperty(AUTO_CONFIGURE_PROPERTY, Boolean.class, false); + } + private void registerNoopTracer(ConfigurableApplicationContext context) { if (AotDetector.useGeneratedArtifacts()) { return; @@ -121,12 +133,12 @@ class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory return false; } DisableObservabilityContextCustomizer that = (DisableObservabilityContextCustomizer) o; - return this.disableMetrics == that.disableMetrics && this.disableTracing == that.disableTracing; + return Objects.equals(this.annotation, that.annotation); } @Override public int hashCode() { - return Objects.hash(this.disableMetrics, this.disableTracing); + return Objects.hash(this.annotation); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json index aae714fa7a..32a5f8cfd4 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json @@ -11,6 +11,12 @@ "type": "org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrint", "description": "MVC Print option.", "defaultValue": "default" + }, + { + "name": "spring.test.observability.auto-configure", + "type": "java.lang.Boolean", + "description": "Whether observability should be auto-configured in tests.", + "defaultValue": "false" } ] -} \ No newline at end of file +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java index a234182bbb..d8e46424c5 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java @@ -29,6 +29,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.ContextCustomizer; import static org.assertj.core.api.Assertions.assertThat; @@ -135,12 +136,68 @@ class ObservabilityContextCustomizerFactoryTests { } @Test - void hashCodeAndEquals() { + void notEquals() { ContextCustomizer customizer1 = createContextCustomizer(OnlyMetrics.class); ContextCustomizer customizer2 = createContextCustomizer(OnlyTracing.class); assertThat(customizer1).isNotEqualTo(customizer2); } + @Test + void equals() { + ContextCustomizer customizer1 = createContextCustomizer(OnlyMetrics.class); + ContextCustomizer customizer2 = createContextCustomizer(OnlyMetrics.class); + assertThat(customizer1).isEqualTo(customizer2); + assertThat(customizer1).hasSameHashCodeAs(customizer2); + } + + @Test + void metricsAndTracingCanBeEnabledViaProperty() { + ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class); + ConfigurableApplicationContext context = new GenericApplicationContext(); + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.test.observability.auto-configure", "true"); + context.setEnvironment(environment); + applyCustomizerToContext(customizer, context); + assertThatMetricsAreEnabled(context); + assertThatTracingIsEnabled(context); + } + + @Test + void metricsAndTracingCanBeDisabledViaProperty() { + ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class); + ConfigurableApplicationContext context = new GenericApplicationContext(); + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.test.observability.auto-configure", "false"); + context.setEnvironment(environment); + applyCustomizerToContext(customizer, context); + assertThatMetricsAreDisabled(context); + assertThatTracingIsDisabled(context); + } + + @Test + void annotationTakesPrecedenceOverDisabledProperty() { + ContextCustomizer customizer = createContextCustomizer(WithAnnotation.class); + ConfigurableApplicationContext context = new GenericApplicationContext(); + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.test.observability.auto-configure", "false"); + context.setEnvironment(environment); + applyCustomizerToContext(customizer, context); + assertThatMetricsAreEnabled(context); + assertThatTracingIsEnabled(context); + } + + @Test + void annotationTakesPrecedenceOverEnabledProperty() { + ContextCustomizer customizer = createContextCustomizer(WithDisabledAnnotation.class); + ConfigurableApplicationContext context = new GenericApplicationContext(); + MockEnvironment environment = new MockEnvironment(); + environment.setProperty("spring.test.observability.auto-configure", "true"); + context.setEnvironment(environment); + applyCustomizerToContext(customizer, context); + assertThatMetricsAreDisabled(context); + assertThatTracingIsDisabled(context); + } + private void applyCustomizerToContext(ContextCustomizer customizer, ConfigurableApplicationContext context) { customizer.customizeContext(context, null); } @@ -194,6 +251,11 @@ class ObservabilityContextCustomizerFactoryTests { } + @AutoConfigureObservability(metrics = false, tracing = false) + static class WithDisabledAnnotation { + + } + @Configuration(proxyBeanMethods = false) static class CustomTracer {