Rework @AutoConfigureObservability and tracing auto-configurations

@ConditionalOnEnabledTracing is now applied to the minimal amount of
beans. The beans which are annotated with it are beans that will lead
to span sending to backends.

This leaves the majority of the Micrometer Tracing, Brave and
OpenTelemetry infrastructure untouched in tests.

Closes gh-35354
This commit is contained in:
Moritz Halbritter 2023-06-16 14:09:00 +02:00
parent fb4b26a842
commit 27add2bbe3
21 changed files with 100 additions and 208 deletions

View File

@ -76,7 +76,6 @@ import org.springframework.core.env.Environment;
@AutoConfiguration(before = MicrometerTracingAutoConfiguration.class)
@ConditionalOnClass({ Tracer.class, BraveTracer.class })
@EnableConfigurationProperties(TracingProperties.class)
@ConditionalOnEnabledTracing
public class BraveAutoConfiguration {
private static final BraveBaggageManager BRAVE_BAGGAGE_MANAGER = new BraveBaggageManager();

View File

@ -39,7 +39,6 @@ import org.springframework.core.annotation.Order;
*/
@AutoConfiguration
@ConditionalOnClass(Tracer.class)
@ConditionalOnEnabledTracing
public class MicrometerTracingAutoConfiguration {
/**

View File

@ -75,7 +75,6 @@ import org.springframework.core.env.Environment;
* @since 3.0.0
*/
@AutoConfiguration(before = MicrometerTracingAutoConfiguration.class)
@ConditionalOnEnabledTracing
@ConditionalOnClass({ OtelTracer.class, SdkTracerProvider.class, OpenTelemetry.class })
@EnableConfigurationProperties(TracingProperties.class)
public class OpenTelemetryAutoConfiguration {

View File

@ -50,7 +50,6 @@ import org.springframework.context.annotation.Bean;
* @since 3.1.0
*/
@AutoConfiguration
@ConditionalOnEnabledTracing
@ConditionalOnClass({ OtelTracer.class, SdkTracerProvider.class, OpenTelemetry.class, OtlpHttpSpanExporter.class })
@EnableConfigurationProperties(OtlpProperties.class)
public class OtlpAutoConfiguration {
@ -59,6 +58,7 @@ public class OtlpAutoConfiguration {
@ConditionalOnMissingBean(value = OtlpHttpSpanExporter.class,
type = "io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter")
@ConditionalOnProperty(prefix = "management.otlp.tracing", name = "endpoint")
@ConditionalOnEnabledTracing
OtlpHttpSpanExporter otlpHttpSpanExporter(OtlpProperties properties) {
OtlpHttpSpanExporterBuilder builder = OtlpHttpSpanExporter.builder()
.setEndpoint(properties.getEndpoint())

View File

@ -22,7 +22,6 @@ import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
import org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -43,7 +42,6 @@ import org.springframework.util.function.SingletonSupplier;
after = MicrometerTracingAutoConfiguration.class)
@ConditionalOnBean(Tracer.class)
@ConditionalOnClass({ Tracer.class, SpanContextSupplier.class })
@ConditionalOnEnabledTracing
public class PrometheusExemplarsAutoConfiguration {
@Bean

View File

@ -52,7 +52,6 @@ import org.springframework.context.annotation.Import;
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
WavefrontAutoConfiguration.class })
@ConditionalOnClass({ WavefrontSender.class, WavefrontSpanHandler.class })
@ConditionalOnEnabledTracing
@EnableConfigurationProperties(WavefrontProperties.class)
@Import(WavefrontSenderConfiguration.class)
public class WavefrontTracingAutoConfiguration {
@ -60,6 +59,7 @@ public class WavefrontTracingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(WavefrontSender.class)
@ConditionalOnEnabledTracing
WavefrontSpanHandler wavefrontSpanHandler(WavefrontProperties properties, WavefrontSender wavefrontSender,
SpanMetrics spanMetrics, ApplicationTags applicationTags) {
return new WavefrontSpanHandler(properties.getSender().getMaxQueueSize(), wavefrontSender, spanMetrics,
@ -96,6 +96,7 @@ public class WavefrontTracingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledTracing
WavefrontBraveSpanHandler wavefrontBraveSpanHandler(WavefrontSpanHandler wavefrontSpanHandler) {
return new WavefrontBraveSpanHandler(wavefrontSpanHandler);
}
@ -108,6 +109,7 @@ public class WavefrontTracingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledTracing
WavefrontOtelSpanExporter wavefrontOtelSpanExporter(WavefrontSpanHandler wavefrontSpanHandler) {
return new WavefrontOtelSpanExporter(wavefrontSpanHandler);
}

View File

@ -21,7 +21,6 @@ import zipkin2.codec.BytesEncoder;
import zipkin2.codec.SpanBytesEncoder;
import zipkin2.reporter.Sender;
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.ReporterConfiguration;
@ -48,7 +47,6 @@ import org.springframework.context.annotation.Import;
@ConditionalOnClass(Sender.class)
@Import({ SenderConfiguration.class, ReporterConfiguration.class, BraveConfiguration.class,
OpenTelemetryConfiguration.class })
@ConditionalOnEnabledTracing
@EnableConfigurationProperties(ZipkinProperties.class)
public class ZipkinAutoConfiguration {

View File

@ -26,6 +26,7 @@ import zipkin2.reporter.brave.ZipkinSpanHandler;
import zipkin2.reporter.urlconnection.URLConnectionSender;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -142,6 +143,7 @@ class ZipkinConfigurations {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Reporter.class)
@ConditionalOnEnabledTracing
ZipkinSpanHandler zipkinSpanHandler(Reporter<Span> spanReporter) {
return (ZipkinSpanHandler) ZipkinSpanHandler.newBuilder(spanReporter).build();
}
@ -155,6 +157,7 @@ class ZipkinConfigurations {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Sender.class)
@ConditionalOnEnabledTracing
ZipkinSpanExporter zipkinSpanExporter(BytesEncoder<Span> encoder, Sender sender) {
return ZipkinSpanExporter.builder().setEncoder(encoder).setSender(sender).build();
}

View File

@ -21,13 +21,17 @@ import java.time.Duration;
import com.wavefront.sdk.common.WavefrontSender;
import com.wavefront.sdk.common.clients.WavefrontClient.Builder;
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
import org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
import org.springframework.boot.actuate.autoconfigure.tracing.wavefront.WavefrontTracingAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
@ -46,6 +50,7 @@ public class WavefrontSenderConfiguration {
@Bean
@ConditionalOnMissingBean
@Conditional(WavefrontTracingOrMetricsCondition.class)
public WavefrontSender wavefrontSender(WavefrontProperties properties) {
Builder builder = new Builder(properties.getEffectiveUri().toString(), properties.getApiTokenOrThrow());
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
@ -57,4 +62,22 @@ public class WavefrontSenderConfiguration {
return builder.build();
}
static final class WavefrontTracingOrMetricsCondition extends AnyNestedCondition {
WavefrontTracingOrMetricsCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnEnabledTracing
static class TracingCondition {
}
@ConditionalOnEnabledMetricsExport("wavefront")
static class MetricsCondition {
}
}
}

View File

@ -19,6 +19,8 @@ package org.springframework.boot.actuate.autoconfigure.integrationtest;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryAutoConfiguration;
import org.springframework.boot.actuate.health.HealthEndpointWebExtension;
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -80,7 +82,8 @@ class WebEndpointsAutoConfigurationIntegrationTests {
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
RepositoryRestMvcAutoConfiguration.class, HazelcastAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class, RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class })
RedisRepositoriesAutoConfiguration.class, BraveAutoConfiguration.class,
OpenTelemetryAutoConfiguration.class })
@SpringBootConfiguration
static class WebEndpointTestApplication {

View File

@ -151,12 +151,6 @@ class BraveAutoConfigurationTests {
});
}
@Test
void shouldNotSupplyBeansIfTracingIsDisabled() {
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(BraveAutoConfiguration.class));
}
@Test
void shouldNotSupplyCorrelationScopeDecoratorIfBaggageDisabled() {
this.contextRunner.withPropertyValues("management.tracing.baggage.enabled=false")

View File

@ -111,17 +111,6 @@ class MicrometerTracingAutoConfigurationTests {
});
}
@Test
void shouldNotSupplyBeansIfTracingIsDisabled() {
this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class)
.withPropertyValues("management.tracing.enabled=false")
.run((context) -> {
assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class);
assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class);
assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class);
});
}
@Configuration(proxyBeanMethods = false)
private static class TracerConfiguration {

View File

@ -40,6 +40,9 @@ class OtlpAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(OtlpAutoConfiguration.class));
private final ApplicationContextRunner tracingDisabledContextRunner = this.contextRunner
.withPropertyValues("management.tracing.enabled=false");
@Test
void shouldNotSupplyBeansIfPropertyIsNotSet() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(OtlpHttpSpanExporter.class));
@ -96,6 +99,13 @@ class OtlpAutoConfigurationTests {
.hasSingleBean(SpanExporter.class));
}
@Test
void shouldNotSupplyOtlpHttpSpanExporterIfTracingIsDisabled() {
this.tracingDisabledContextRunner
.withPropertyValues("management.otlp.tracing.endpoint=http://localhost:4318/v1/traces")
.run((context) -> assertThat(context).doesNotHaveBean(OtlpHttpSpanExporter.class));
}
@Configuration(proxyBeanMethods = false)
private static class CustomHttpExporterConfiguration {

View File

@ -40,7 +40,7 @@ import static org.mockito.Mockito.mock;
/**
* Tests for {@link PrometheusExemplarsAutoConfiguration}.
*
* * @author Jonatan Ivanov
* @author Jonatan Ivanov
*/
class PrometheusExemplarsAutoConfigurationTests {
@ -52,12 +52,6 @@ class PrometheusExemplarsAutoConfigurationTests {
AutoConfigurations.of(PrometheusExemplarsAutoConfiguration.class, ObservationAutoConfiguration.class,
BraveAutoConfiguration.class, MicrometerTracingAutoConfiguration.class));
@Test
void shouldNotSupplyBeansIfTracingIsDisabled() {
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(SpanContextSupplier.class));
}
@Test
void shouldNotSupplyBeansIfPrometheusSupportIsMissing() {
this.contextRunner.withClassLoader(new FilteredClassLoader("io.prometheus.client.exemplars"))

View File

@ -47,6 +47,9 @@ class WavefrontTracingAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
AutoConfigurations.of(WavefrontAutoConfiguration.class, WavefrontTracingAutoConfiguration.class));
private final ApplicationContextRunner tracingDisabledContextRunner = this.contextRunner
.withPropertyValues("management.tracing.enabled=false");
@Test
void shouldSupplyBeans() {
this.contextRunner.withUserConfiguration(WavefrontSenderConfiguration.class).run((context) -> {
@ -83,14 +86,11 @@ class WavefrontTracingAutoConfigurationTests {
@Test
void shouldNotSupplyBeansIfTracingIsDisabled() {
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
.withUserConfiguration(WavefrontSenderConfiguration.class)
.run((context) -> {
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
assertThat(context).doesNotHaveBean(SpanMetrics.class);
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
});
this.tracingDisabledContextRunner.withUserConfiguration(WavefrontSenderConfiguration.class).run((context) -> {
assertThat(context).doesNotHaveBean(WavefrontSpanHandler.class);
assertThat(context).doesNotHaveBean(WavefrontBraveSpanHandler.class);
assertThat(context).doesNotHaveBean(WavefrontOtelSpanExporter.class);
});
}
@Test

View File

@ -59,12 +59,6 @@ class ZipkinAutoConfigurationTests {
});
}
@Test
void shouldNotSupplyBeansIfTracingIsDisabled() {
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(BytesEncoder.class));
}
@Test
void definesPropertiesBasedConnectionDetailsByDefault() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesZipkinConnectionDetails.class));

View File

@ -42,6 +42,9 @@ class ZipkinConfigurationsBraveConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(BraveConfiguration.class));
private final ApplicationContextRunner tracingDisabledContextRunner = this.contextRunner
.withPropertyValues("management.tracing.enabled=false");
@Test
void shouldSupplyBeans() {
this.contextRunner.withUserConfiguration(ReporterConfiguration.class)
@ -79,6 +82,12 @@ class ZipkinConfigurationsBraveConfigurationTests {
});
}
@Test
void shouldNotSupplyZipkinSpanHandlerIfTracingIsDisabled() {
this.tracingDisabledContextRunner.withUserConfiguration(ReporterConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanHandler.class));
}
@Configuration(proxyBeanMethods = false)
private static class ReporterConfiguration {

View File

@ -43,6 +43,9 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(BaseConfiguration.class, OpenTelemetryConfiguration.class));
private final ApplicationContextRunner tracingDisabledContextRunner = this.contextRunner
.withPropertyValues("management.tracing.enabled=false");
@Test
void shouldSupplyBeans() {
this.contextRunner.withUserConfiguration(SenderConfiguration.class)
@ -70,6 +73,12 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
});
}
@Test
void shouldNotSupplyZipkinSpanExporterIfTracingIsDisabled() {
this.tracingDisabledContextRunner.withUserConfiguration(SenderConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class));
}
@Configuration(proxyBeanMethods = false)
private static class SenderConfiguration {

View File

@ -42,6 +42,17 @@ class WavefrontSenderConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WavefrontSenderConfiguration.class));
private final ApplicationContextRunner tracingDisabledContextRunner = this.contextRunner
.withPropertyValues("management.tracing.enabled=false");
private final ApplicationContextRunner metricsDisabledContextRunner = this.contextRunner.withPropertyValues(
"management.defaults.metrics.export.enabled=false", "management.simple.metrics.export.enabled=true");
// Both metrics and tracing are disabled
private final ApplicationContextRunner observabilityDisabledContextRunner = this.contextRunner.withPropertyValues(
"management.tracing.enabled=false", "management.defaults.metrics.export.enabled=false",
"management.simple.metrics.export.enabled=true");
@Test
void shouldNotFailIfWavefrontIsMissing() {
this.contextRunner.withClassLoader(new FilteredClassLoader("com.wavefront"))
@ -83,6 +94,24 @@ class WavefrontSenderConfigurationTests {
});
}
@Test
void shouldNotSupplyWavefrontSenderIfObservabilityIsDisabled() {
this.observabilityDisabledContextRunner.withPropertyValues("management.wavefront.api-token=abcde")
.run((context) -> assertThat(context).doesNotHaveBean(WavefrontSender.class));
}
@Test
void shouldSupplyWavefrontSenderIfOnlyTracingIsDisabled() {
this.tracingDisabledContextRunner.withPropertyValues("management.wavefront.api-token=abcde")
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class));
}
@Test
void shouldSupplyWavefrontSenderIfOnlyMetricsAreDisabled() {
this.metricsDisabledContextRunner.withPropertyValues("management.wavefront.api-token=abcde")
.run((context) -> assertThat(context).hasSingleBean(WavefrontSender.class));
}
@Test
void allowsWavefrontSenderToBeCustomized() {
this.contextRunner.withUserConfiguration(CustomSenderConfiguration.class)

View File

@ -19,39 +19,19 @@ package org.springframework.boot.test.autoconfigure.actuate.observability;
import java.util.List;
import java.util.Objects;
import io.micrometer.tracing.Tracer;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
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;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.util.ClassUtils;
/**
* {@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.
* <p>
* Registers {@link Tracer#NOOP} if tracing is disabled, micrometer-tracing is on the
* classpath, and the user hasn't supplied their own {@link Tracer}.
*
* @author Chris Bono
* @author Moritz Halbritter
@ -87,7 +67,6 @@ class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory
}
if (isTracingDisabled(context.getEnvironment())) {
TestPropertyValues.of("management.tracing.enabled=false").applyTo(context);
registerNoopTracer(context);
}
}
@ -105,25 +84,6 @@ class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory
return !environment.getProperty(AUTO_CONFIGURE_PROPERTY, Boolean.class, false);
}
private void registerNoopTracer(ConfigurableApplicationContext context) {
if (AotDetector.useGeneratedArtifacts()) {
return;
}
if (!ClassUtils.isPresent("io.micrometer.tracing.Tracer", context.getClassLoader())) {
return;
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
registerNoopTracer(registry);
}
}
private void registerNoopTracer(BeanDefinitionRegistry registry) {
RootBeanDefinition definition = new RootBeanDefinition(NoopTracerRegistrar.class);
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(NoopTracerRegistrar.class.getName(), definition);
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -143,54 +103,4 @@ class ObservabilityContextCustomizerFactory implements ContextCustomizerFactory
}
/**
* {@link BeanDefinitionRegistryPostProcessor} that runs after the
* {@link ConfigurationClassPostProcessor} and adds a {@link Tracer} bean definition
* when a {@link Tracer} hasn't already been registered.
*/
static class NoopTracerRegistrar implements BeanDefinitionRegistryPostProcessor, Ordered, BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (AotDetector.useGeneratedArtifacts()) {
return;
}
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors((ListableBeanFactory) this.beanFactory,
Tracer.class, false, false).length == 0) {
registry.registerBeanDefinition("noopTracer", new RootBeanDefinition(NoopTracerFactoryBean.class));
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
static class NoopTracerFactoryBean implements FactoryBean<Tracer> {
@Override
public Tracer getObject() {
return Tracer.NOOP;
}
@Override
public Class<?> getObjectType() {
return Tracer.class;
}
}
}

View File

@ -18,22 +18,15 @@ package org.springframework.boot.test.autoconfigure.actuate.observability;
import java.util.Collections;
import io.micrometer.tracing.Tracer;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.annotation.UserConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContextInitializer;
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;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link AutoConfigureObservability} and
@ -82,59 +75,6 @@ class ObservabilityContextCustomizerFactoryTests {
assertThatTracingIsEnabled(context);
}
@Test
void shouldRegisterNoopTracerIfTracingIsDisabled() {
ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class);
ConfigurableApplicationContext context = new GenericApplicationContext();
applyCustomizerToContext(customizer, context);
context.refresh();
Tracer tracer = context.getBean(Tracer.class);
assertThat(tracer).isNotNull();
assertThat(tracer.nextSpan().isNoop()).isTrue();
}
@Test
void shouldNotRegisterNoopTracerIfTracingIsEnabled() {
ContextCustomizer customizer = createContextCustomizer(WithAnnotation.class);
ConfigurableApplicationContext context = new GenericApplicationContext();
applyCustomizerToContext(customizer, context);
context.refresh();
assertThat(context.getBeanProvider(Tracer.class).getIfAvailable()).as("Tracer bean").isNull();
}
@Test
void shouldNotRegisterNoopTracerIfMicrometerTracingIsNotPresent() throws Exception {
try (FilteredClassLoader filteredClassLoader = new FilteredClassLoader("io.micrometer.tracing")) {
ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class);
new ApplicationContextRunner().withClassLoader(filteredClassLoader)
.withInitializer(applyCustomizer(customizer))
.run((context) -> {
assertThat(context).doesNotHaveBean(Tracer.class);
assertThatMetricsAreDisabled(context);
assertThatTracingIsDisabled(context);
});
}
}
@Test
void shouldBackOffOnCustomTracer() {
ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class);
new ApplicationContextRunner().withConfiguration(UserConfigurations.of(CustomTracer.class))
.withInitializer(applyCustomizer(customizer))
.run((context) -> {
assertThat(context).hasSingleBean(Tracer.class);
assertThat(context).hasBean("customTracer");
});
}
@Test
void shouldNotRunIfAotIsEnabled() {
ContextCustomizer customizer = createContextCustomizer(NoAnnotation.class);
new ApplicationContextRunner().withSystemProperties("spring.aot.enabled:true")
.withInitializer(applyCustomizer(customizer))
.run((context) -> assertThat(context).doesNotHaveBean(Tracer.class));
}
@Test
void notEquals() {
ContextCustomizer customizer1 = createContextCustomizer(OnlyMetrics.class);
@ -256,14 +196,4 @@ class ObservabilityContextCustomizerFactoryTests {
}
@Configuration(proxyBeanMethods = false)
static class CustomTracer {
@Bean
Tracer customTracer() {
return mock(Tracer.class);
}
}
}