From b250d8a1e4e0547763b8970e78458bd936a86153 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Fri, 10 Jun 2022 11:36:55 +0200 Subject: [PATCH] Add @AutoConfigureObservability annotation This annotation is read by ObservabilityContextCustomizerFactory, which then sets test properties depending on the annotation attributes. @AutoConfigureMetrics is deprecated, to support backwards compatability it's now meta-annotated with @AutoConfigureObservability See gh-31308 --- .../src/docs/asciidoc/features/testing.adoc | 2 +- .../actuate/metrics/AutoConfigureMetrics.java | 7 +- ...MetricsExportContextCustomizerFactory.java | 66 --------- .../AutoConfigureObservability.java | 51 +++++++ ...ObservabilityContextCustomizerFactory.java | 93 +++++++++++++ .../actuate/observability/package-info.java | 20 +++ .../main/resources/META-INF/spring.factories | 2 +- ...nfigureMetricsPresentIntegrationTests.java | 1 + ...ConfigureMetricsSpringBootApplication.java | 7 +- ...csExportContextCustomizerFactoryTests.java | 78 ----------- ...eObservabilityMissingIntegrationTests.java | 56 ++++++++ ...eObservabilityPresentIntegrationTests.java | 54 ++++++++ ...ureObservabilitySpringBootApplication.java | 38 ++++++ ...vabilityContextCustomizerFactoryTests.java | 127 ++++++++++++++++++ 14 files changed, 453 insertions(+), 149 deletions(-) delete mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactory.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservability.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/package-info.java delete mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactoryTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityMissingIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityPresentIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilitySpringBootApplication.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index d483582753..6a4496888f 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -226,7 +226,7 @@ include::code:MyJmxTests[] ==== Using Metrics Regardless of your classpath, meter registries, except the in-memory backed, are not auto-configured when using `@SpringBootTest`. -If you need to export metrics to a different backend as part of an integration test, annotate it with `@AutoConfigureMetrics`. +If you need to export metrics to a different backend as part of an integration test, annotate it with `@AutoConfigureObservability`. diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetrics.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetrics.java index 50e76a3098..6ec6ada754 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetrics.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,17 +23,22 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; + /** * Annotation that can be applied to a test class to enable auto-configuration for metrics * exporters. * * @author Chris Bono * @since 2.4.0 + * @deprecated use {@link AutoConfigureObservability} instead */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited +@Deprecated +@AutoConfigureObservability(tracing = false) public @interface AutoConfigureMetrics { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactory.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactory.java deleted file mode 100644 index 597ea3168c..0000000000 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.test.autoconfigure.actuate.metrics; - -import java.util.List; - -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.test.context.ContextConfigurationAttributes; -import org.springframework.test.context.ContextCustomizer; -import org.springframework.test.context.ContextCustomizerFactory; -import org.springframework.test.context.MergedContextConfiguration; -import org.springframework.test.context.TestContextAnnotationUtils; - -/** - * {@link ContextCustomizerFactory} that globally disables metrics export unless - * {@link AutoConfigureMetrics} is set on the test class. - * - * @author Chris Bono - */ -class MetricsExportContextCustomizerFactory implements ContextCustomizerFactory { - - @Override - public ContextCustomizer createContextCustomizer(Class testClass, - List configAttributes) { - boolean disableMetricsExport = TestContextAnnotationUtils.findMergedAnnotation(testClass, - AutoConfigureMetrics.class) == null; - return disableMetricsExport ? new DisableMetricExportContextCustomizer() : null; - } - - static class DisableMetricExportContextCustomizer implements ContextCustomizer { - - @Override - public void customizeContext(ConfigurableApplicationContext context, - MergedContextConfiguration mergedContextConfiguration) { - TestPropertyValues.of("management.defaults.metrics.export.enabled=false", - "management.simple.metrics.export.enabled=true").applyTo(context); - } - - @Override - public boolean equals(Object obj) { - return (obj != null) && (getClass() == obj.getClass()); - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } - - } - -} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservability.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservability.java new file mode 100644 index 0000000000..a72bf7c4c4 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservability.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that can be applied to a test class to enable auto-configuration for + * observability. + * + * @author Moritz Halbritter + * @since 3.0.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface AutoConfigureObservability { + + /** + * Whether metrics should be enabled in the test. + * @return whether metrics should be enabled in the test + */ + boolean metrics() default true; + + /** + * Whether tracing should be enabled in the test. + * @return whether metrics should be enabled in the test + */ + boolean tracing() default true; + +} 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 new file mode 100644 index 0000000000..f22fbaf997 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactory.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import java.util.List; +import java.util.Objects; + +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.context.TestContextAnnotationUtils; + +/** + * {@link ContextCustomizerFactory} that globally disables metrics export unless + * {@link AutoConfigureObservability} is set on the test class. + * + * @author Chris Bono + * @author Moritz Halbritter + */ +class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory { + + @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()); + } + + static class DisableObservabilityContextCustomizer implements ContextCustomizer { + + private final boolean disableMetrics; + + private final boolean disableTracing; + + DisableObservabilityContextCustomizer(boolean disableMetrics, boolean disableTracing) { + this.disableMetrics = disableMetrics; + this.disableTracing = disableTracing; + } + + @Override + public void customizeContext(ConfigurableApplicationContext context, + MergedContextConfiguration mergedContextConfiguration) { + if (this.disableMetrics) { + TestPropertyValues.of("management.defaults.metrics.export.enabled=false", + "management.simple.metrics.export.enabled=true").applyTo(context); + } + if (this.disableTracing) { + TestPropertyValues.of("management.tracing.enabled=false").applyTo(context); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DisableObservabilityContextCustomizer that = (DisableObservabilityContextCustomizer) o; + return this.disableMetrics == that.disableMetrics && this.disableTracing == that.disableTracing; + } + + @Override + public int hashCode() { + return Objects.hash(this.disableMetrics, this.disableTracing); + } + + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/package-info.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/package-info.java new file mode 100644 index 0000000000..7fcb9b8440 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/actuate/observability/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Auto-configuration for handling observability in tests. + */ +package org.springframework.boot.test.autoconfigure.actuate.observability; diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories index 2648ce2b0a..5a0cf67166 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories @@ -5,7 +5,7 @@ org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExe # Spring Test ContextCustomizerFactories org.springframework.test.context.ContextCustomizerFactory=\ org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory,\ -org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory,\ +org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory,\ org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizerFactory,\ org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizerFactory,\ org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsPresentIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsPresentIntegrationTests.java index ff77d29f27..4a2780c957 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsPresentIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsPresentIntegrationTests.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Chris Bono */ +@SuppressWarnings("deprecation") @SpringBootTest @AutoConfigureMetrics class AutoConfigureMetricsPresentIntegrationTests { diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java index c17d00d087..31c699a44b 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; /** * Example {@link SpringBootApplication @SpringBootApplication} for use with @@ -28,7 +30,8 @@ import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfigurati * @author Chris Bono */ @SpringBootConfiguration -@EnableAutoConfiguration(exclude = CassandraAutoConfiguration.class) +@EnableAutoConfiguration(exclude = { CassandraAutoConfiguration.class, MongoAutoConfiguration.class, + MongoReactiveAutoConfiguration.class }) class AutoConfigureMetricsSpringBootApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactoryTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactoryTests.java deleted file mode 100644 index 573b6366d8..0000000000 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/MetricsExportContextCustomizerFactoryTests.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.test.autoconfigure.actuate.metrics; - -import java.util.Collections; - -import org.junit.jupiter.api.Test; - -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.test.context.ContextCustomizer; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link AutoConfigureMetrics} and - * {@link MetricsExportContextCustomizerFactory} working together. - * - * @author Chris Bono - */ -class MetricsExportContextCustomizerFactoryTests { - - private final MetricsExportContextCustomizerFactory factory = new MetricsExportContextCustomizerFactory(); - - @Test - void getContextCustomizerWhenHasNoAnnotationShouldReturnCustomizer() { - ContextCustomizer customizer = this.factory.createContextCustomizer(NoAnnotation.class, - Collections.emptyList()); - assertThat(customizer).isNotNull(); - ConfigurableApplicationContext context = new GenericApplicationContext(); - customizer.customizeContext(context, null); - assertThat(context.getEnvironment().getProperty("management.defaults.metrics.export.enabled")) - .isEqualTo("false"); - assertThat(context.getEnvironment().getProperty("management.simple.metrics.export.enabled")).isEqualTo("true"); - } - - @Test - void getContextCustomizerWhenHasAnnotationShouldReturnNull() { - ContextCustomizer customizer = this.factory.createContextCustomizer(WithAnnotation.class, null); - assertThat(customizer).isNull(); - } - - @Test - void hashCodeAndEquals() { - ContextCustomizer customizer1 = this.factory.createContextCustomizer(NoAnnotation.class, null); - ContextCustomizer customizer2 = this.factory.createContextCustomizer(OtherWithNoAnnotation.class, null); - assertThat(customizer1.hashCode()).isEqualTo(customizer2.hashCode()); - assertThat(customizer1).isEqualTo(customizer1).isEqualTo(customizer2); - } - - static class NoAnnotation { - - } - - static class OtherWithNoAnnotation { - - } - - @AutoConfigureMetrics - static class WithAnnotation { - - } - -} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityMissingIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityMissingIntegrationTests.java new file mode 100644 index 0000000000..e0aa060094 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityMissingIntegrationTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration test to verify behaviour when + * {@link AutoConfigureObservability @AutoConfigureObservability} is not present on the + * test class. + * + * @author Chris Bono + * @author Moritz Halbritter + */ +@SpringBootTest +class AutoConfigureObservabilityMissingIntegrationTests { + + @Test + void customizerRunsAndOnlyEnablesSimpleMeterRegistryWhenNoAnnotationPresent( + @Autowired ApplicationContext applicationContext) { + assertThat(applicationContext.getBean(MeterRegistry.class)).isInstanceOf(SimpleMeterRegistry.class); + assertThat(applicationContext.getBeansOfType(PrometheusMeterRegistry.class)).isEmpty(); + } + + @Test + void customizerRunsAndSetsExclusionPropertiesWhenNoAnnotationPresent(@Autowired Environment environment) { + assertThat(environment.getProperty("management.defaults.metrics.export.enabled")).isEqualTo("false"); + assertThat(environment.getProperty("management.simple.metrics.export.enabled")).isEqualTo("true"); + assertThat(environment.getProperty("management.tracing.enabled")).isEqualTo("false"); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityPresentIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityPresentIntegrationTests.java new file mode 100644 index 0000000000..d4fbdcef56 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilityPresentIntegrationTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import io.micrometer.prometheus.PrometheusMeterRegistry; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration test to verify behaviour when + * {@link AutoConfigureObservability @AutoConfigureObservability} is present on the test + * class. + * + * @author Chris Bono + * @author Moritz Halbritter + */ +@SpringBootTest +@AutoConfigureObservability +class AutoConfigureObservabilityPresentIntegrationTests { + + @Test + void customizerDoesNotDisableAvailableMeterRegistriesWhenAnnotationPresent( + @Autowired ApplicationContext applicationContext) { + assertThat(applicationContext.getBeansOfType(PrometheusMeterRegistry.class)).hasSize(1); + } + + @Test + void customizerDoesNotSetExclusionPropertiesWhenAnnotationPresent(@Autowired Environment environment) { + assertThat(environment.containsProperty("management.defaults.metrics.export.enabled")).isFalse(); + assertThat(environment.containsProperty("management.simple.metrics.export.enabled")).isFalse(); + assertThat(environment.containsProperty("management.tracing.enabled")).isFalse(); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilitySpringBootApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilitySpringBootApplication.java new file mode 100644 index 0000000000..de9517206a --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/AutoConfigureObservabilitySpringBootApplication.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; + +/** + * Example {@link SpringBootApplication @SpringBootApplication} for use with + * {@link AutoConfigureObservability @AutoConfigureObservability} tests. + * + * @author Chris Bono + * @author Moritz Halbritter + */ +@SpringBootConfiguration +@EnableAutoConfiguration(exclude = { CassandraAutoConfiguration.class, MongoReactiveAutoConfiguration.class, + MongoAutoConfiguration.class }) +class AutoConfigureObservabilitySpringBootApplication { + +} 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 new file mode 100644 index 0000000000..01f03ffcf9 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/observability/ObservabilityContextCustomizerFactoryTests.java @@ -0,0 +1,127 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.actuate.observability; + +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.test.context.ContextCustomizer; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link AutoConfigureObservability} and + * {@link ObservabilityContextCustomizerFactory} working together. + * + * @author Chris Bono + * @author Moritz Halbritter + */ +class ObservabilityContextCustomizerFactoryTests { + + private final ObservabilityContextCustomizerFactory factory = new ObservabilityContextCustomizerFactory(); + + @Test + void shouldDisableBothWhenNotAnnotated() { + ContextCustomizer customizer = this.factory.createContextCustomizer(NoAnnotation.class, + Collections.emptyList()); + assertThat(customizer).isNotNull(); + ConfigurableApplicationContext context = new GenericApplicationContext(); + customizer.customizeContext(context, null); + assertThatMetricsAreDisabled(context); + assertThatTracingIsDisabled(context); + } + + @Test + void shouldDisableOnlyTracing() { + ContextCustomizer customizer = this.factory.createContextCustomizer(OnlyMetrics.class, Collections.emptyList()); + assertThat(customizer).isNotNull(); + ConfigurableApplicationContext context = new GenericApplicationContext(); + customizer.customizeContext(context, null); + assertThatMetricsAreEnabled(context); + assertThatTracingIsDisabled(context); + } + + @Test + void shouldDisableOnlyMetrics() { + ContextCustomizer customizer = this.factory.createContextCustomizer(OnlyTracing.class, Collections.emptyList()); + assertThat(customizer).isNotNull(); + ConfigurableApplicationContext context = new GenericApplicationContext(); + customizer.customizeContext(context, null); + assertThatMetricsAreDisabled(context); + assertThatTracingIsEnabled(context); + } + + @Test + void shouldEnableBothWhenAnnotated() { + ContextCustomizer customizer = this.factory.createContextCustomizer(WithAnnotation.class, + Collections.emptyList()); + assertThat(customizer).isNotNull(); + ConfigurableApplicationContext context = new GenericApplicationContext(); + customizer.customizeContext(context, null); + assertThatMetricsAreEnabled(context); + assertThatTracingIsEnabled(context); + } + + @Test + void hashCodeAndEquals() { + ContextCustomizer customizer1 = this.factory.createContextCustomizer(OnlyMetrics.class, null); + ContextCustomizer customizer2 = this.factory.createContextCustomizer(OnlyTracing.class, null); + assertThat(customizer1).isNotEqualTo(customizer2); + } + + private void assertThatTracingIsDisabled(ConfigurableApplicationContext context) { + assertThat(context.getEnvironment().getProperty("management.tracing.enabled")).isEqualTo("false"); + } + + private void assertThatMetricsAreDisabled(ConfigurableApplicationContext context) { + assertThat(context.getEnvironment().getProperty("management.defaults.metrics.export.enabled")) + .isEqualTo("false"); + assertThat(context.getEnvironment().getProperty("management.simple.metrics.export.enabled")).isEqualTo("true"); + } + + private void assertThatTracingIsEnabled(ConfigurableApplicationContext context) { + assertThat(context.getEnvironment().getProperty("management.tracing.enabled")).isNull(); + } + + private void assertThatMetricsAreEnabled(ConfigurableApplicationContext context) { + assertThat(context.getEnvironment().getProperty("management.defaults.metrics.export.enabled")).isNull(); + assertThat(context.getEnvironment().getProperty("management.simple.metrics.export.enabled")).isNull(); + } + + static class NoAnnotation { + + } + + @AutoConfigureObservability(tracing = false) + static class OnlyMetrics { + + } + + @AutoConfigureObservability(metrics = false) + static class OnlyTracing { + + } + + @AutoConfigureObservability + static class WithAnnotation { + + } + +}