mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
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:
parent
fb4b26a842
commit
27add2bbe3
@ -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();
|
||||
|
@ -39,7 +39,6 @@ import org.springframework.core.annotation.Order;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(Tracer.class)
|
||||
@ConditionalOnEnabledTracing
|
||||
public class MicrometerTracingAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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,11 +86,8 @@ class WavefrontTracingAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void shouldNotSupplyBeansIfTracingIsDisabled() {
|
||||
this.contextRunner.withPropertyValues("management.tracing.enabled=false")
|
||||
.withUserConfiguration(WavefrontSenderConfiguration.class)
|
||||
.run((context) -> {
|
||||
this.tracingDisabledContextRunner.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);
|
||||
});
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user