diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfiguration.java index 8a1a3a2fc1..74bc43a06a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfiguration.java @@ -16,25 +16,138 @@ package org.springframework.boot.actuate.autoconfigure.tracing; -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.MicrometerConfiguration; -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.SdkConfiguration; -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.TracerConfiguration; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import io.micrometer.tracing.SamplerFunction; +import io.micrometer.tracing.otel.bridge.DefaultHttpClientAttributesGetter; +import io.micrometer.tracing.otel.bridge.DefaultHttpServerAttributesExtractor; +import io.micrometer.tracing.otel.bridge.OtelBaggageManager; +import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext; +import io.micrometer.tracing.otel.bridge.OtelHttpClientHandler; +import io.micrometer.tracing.otel.bridge.OtelHttpServerHandler; +import io.micrometer.tracing.otel.bridge.OtelTracer; +import io.micrometer.tracing.otel.bridge.OtelTracer.EventPublisher; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; + +import org.springframework.boot.SpringBootVersion; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.Import; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; /** * {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry. * - * It uses imports on {@link OpenTelemetryConfigurations} to guarantee the correct - * configuration ordering. - * * @author Moritz Halbritter * @since 3.0.0 */ @AutoConfiguration(before = MicrometerTracingAutoConfiguration.class) -@Import({ SdkConfiguration.class, TracerConfiguration.class, MicrometerConfiguration.class }) @ConditionalOnEnabledTracing +@ConditionalOnClass({ OtelTracer.class, SdkTracerProvider.class, OpenTelemetry.class }) +@EnableConfigurationProperties(TracingProperties.class) public class OpenTelemetryAutoConfiguration { + /** + * Default value for application name if {@code spring.application.name} is not set. + */ + private static final String DEFAULT_APPLICATION_NAME = "application"; + + @Bean + @ConditionalOnMissingBean + OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagators contextPropagators) { + return OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).setPropagators(contextPropagators) + .build(); + } + + @Bean + @ConditionalOnMissingBean + SdkTracerProvider otelSdkTracerProvider(Environment environment, List spanProcessors, + Sampler sampler) { + String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); + SdkTracerProviderBuilder builder = SdkTracerProvider.builder().setSampler(sampler) + .setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName))); + for (SpanProcessor spanProcessor : spanProcessors) { + builder.addSpanProcessor(spanProcessor); + } + return builder.build(); + } + + @Bean + @ConditionalOnMissingBean + ContextPropagators otelContextPropagators(List textMapPropagators) { + return ContextPropagators.create(TextMapPropagator.composite(textMapPropagators)); + } + + @Bean + @ConditionalOnMissingBean + Sampler otelSampler(TracingProperties properties) { + return Sampler.traceIdRatioBased(properties.getSampling().getProbability()); + } + + @Bean + @ConditionalOnMissingBean + SpanProcessor otelSpanProcessor(List spanExporter) { + return SpanProcessor.composite(spanExporter.stream() + .map((exporter) -> BatchSpanProcessor.builder(exporter).build()).collect(Collectors.toList())); + } + + @Bean + @ConditionalOnMissingBean + Tracer otelTracer(OpenTelemetry openTelemetry) { + return openTelemetry.getTracer("org.springframework.boot", SpringBootVersion.getVersion()); + } + + @Bean + @ConditionalOnMissingBean + OtelTracer micrometerOtelTracer(Tracer tracer, EventPublisher eventPublisher, + OtelCurrentTraceContext otelCurrentTraceContext) { + return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher, + new OtelBaggageManager(otelCurrentTraceContext, List.of(), List.of())); + } + + @Bean + @ConditionalOnMissingBean + EventPublisher otelTracerEventPublisher() { + return (event) -> { + }; + } + + @Bean + @ConditionalOnMissingBean + OtelCurrentTraceContext otelCurrentTraceContext() { + return new OtelCurrentTraceContext(); + } + + @Bean + @ConditionalOnMissingBean + OtelHttpClientHandler otelHttpClientHandler(OpenTelemetry openTelemetry) { + return new OtelHttpClientHandler(openTelemetry, null, null, SamplerFunction.deferDecision(), + new DefaultHttpClientAttributesGetter()); + } + + @Bean + @ConditionalOnMissingBean + OtelHttpServerHandler otelHttpServerHandler(OpenTelemetry openTelemetry) { + return new OtelHttpServerHandler(openTelemetry, null, null, Pattern.compile(""), + new DefaultHttpServerAttributesExtractor()); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurations.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurations.java deleted file mode 100644 index bdeaf11cb5..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurations.java +++ /dev/null @@ -1,173 +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.actuate.autoconfigure.tracing; - -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import io.micrometer.tracing.SamplerFunction; -import io.micrometer.tracing.otel.bridge.DefaultHttpClientAttributesGetter; -import io.micrometer.tracing.otel.bridge.DefaultHttpServerAttributesExtractor; -import io.micrometer.tracing.otel.bridge.OtelBaggageManager; -import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext; -import io.micrometer.tracing.otel.bridge.OtelHttpClientHandler; -import io.micrometer.tracing.otel.bridge.OtelHttpServerHandler; -import io.micrometer.tracing.otel.bridge.OtelTracer; -import io.micrometer.tracing.otel.bridge.OtelTracer.EventPublisher; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import io.opentelemetry.sdk.trace.samplers.Sampler; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; - -import org.springframework.boot.SpringBootVersion; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; - -/** - * Configurations for OpenTelemetry. Those are imported by - * {@link OpenTelemetryAutoConfiguration}. - * - * @author Moritz Halbritter - */ -class OpenTelemetryConfigurations { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(SdkTracerProvider.class) - @EnableConfigurationProperties(TracingProperties.class) - static class SdkConfiguration { - - /** - * Default value for application name if {@code spring.application.name} is not - * set. - */ - private static final String DEFAULT_APPLICATION_NAME = "application"; - - @Bean - @ConditionalOnMissingBean - OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagators contextPropagators) { - return OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).setPropagators(contextPropagators) - .build(); - } - - @Bean - @ConditionalOnMissingBean - SdkTracerProvider otelSdkTracerProvider(Environment environment, List spanProcessors, - Sampler sampler) { - String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); - SdkTracerProviderBuilder builder = SdkTracerProvider.builder().setSampler(sampler) - .setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName))); - for (SpanProcessor spanProcessor : spanProcessors) { - builder.addSpanProcessor(spanProcessor); - } - return builder.build(); - } - - @Bean - @ConditionalOnMissingBean - ContextPropagators otelContextPropagators(List textMapPropagators) { - return ContextPropagators.create(TextMapPropagator.composite(textMapPropagators)); - } - - @Bean - @ConditionalOnMissingBean - Sampler otelSampler(TracingProperties properties) { - return Sampler.traceIdRatioBased(properties.getSampling().getProbability()); - } - - @Bean - @ConditionalOnMissingBean - SpanProcessor otelSpanProcessor(List spanExporter) { - return SpanProcessor.composite(spanExporter.stream() - .map((exporter) -> BatchSpanProcessor.builder(exporter).build()).collect(Collectors.toList())); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(Tracer.class) - static class TracerConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(OpenTelemetry.class) - Tracer otelTracer(OpenTelemetry openTelemetry) { - return openTelemetry.getTracer("org.springframework.boot", SpringBootVersion.getVersion()); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(OtelTracer.class) - static class MicrometerConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(Tracer.class) - OtelTracer micrometerOtelTracer(Tracer tracer, EventPublisher eventPublisher, - OtelCurrentTraceContext otelCurrentTraceContext) { - return new OtelTracer(tracer, otelCurrentTraceContext, eventPublisher, - new OtelBaggageManager(otelCurrentTraceContext, List.of(), List.of())); - } - - @Bean - @ConditionalOnMissingBean - EventPublisher otelTracerEventPublisher() { - return (event) -> { - }; - } - - @Bean - @ConditionalOnMissingBean - OtelCurrentTraceContext otelCurrentTraceContext() { - return new OtelCurrentTraceContext(); - } - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(OpenTelemetry.class) - OtelHttpClientHandler otelHttpClientHandler(OpenTelemetry openTelemetry) { - return new OtelHttpClientHandler(openTelemetry, null, null, SamplerFunction.deferDecision(), - new DefaultHttpClientAttributesGetter()); - } - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(OpenTelemetry.class) - OtelHttpServerHandler otelHttpServerHandler(OpenTelemetry openTelemetry) { - return new OtelHttpServerHandler(openTelemetry, null, null, Pattern.compile(""), - new DefaultHttpServerAttributesExtractor()); - } - - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsMicrometerConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfigurationTests.java similarity index 50% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsMicrometerConfigurationTests.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfigurationTests.java index 565fa8abef..23440f28b1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsMicrometerConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryAutoConfigurationTests.java @@ -23,10 +23,14 @@ import io.micrometer.tracing.otel.bridge.OtelTracer; import io.micrometer.tracing.otel.bridge.OtelTracer.EventPublisher; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; import org.junit.jupiter.api.Test; -import org.mockito.Answers; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.MicrometerConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -37,49 +41,48 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; /** - * Tests for {@link MicrometerConfiguration}. + * Tests for {@link OpenTelemetryAutoConfiguration}. * * @author Moritz Halbritter + * @author Andy Wilkinson */ -class OpenTelemetryConfigurationsMicrometerConfigurationTests { +class OpenTelemetryAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(MicrometerConfiguration.class)); + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)); @Test void shouldSupplyBeans() { - this.contextRunner.withUserConfiguration(TracerConfiguration.class, OpenTelemetryConfiguration.class) - .run((context) -> { - assertThat(context).hasSingleBean(OtelTracer.class); - assertThat(context).hasSingleBean(EventPublisher.class); - assertThat(context).hasSingleBean(OtelCurrentTraceContext.class); - assertThat(context).hasSingleBean(OtelHttpClientHandler.class); - assertThat(context).hasSingleBean(OtelHttpServerHandler.class); - }); - } - - @Test - void shouldNotSupplyBeansIfMicrometerTracingBridgeOtelIsMissing() { - this.contextRunner.withClassLoader(new FilteredClassLoader("io.micrometer.tracing.otel")) - .withUserConfiguration(TracerConfiguration.class, OpenTelemetryConfiguration.class).run((context) -> { - assertThat(context).doesNotHaveBean(OtelTracer.class); - assertThat(context).doesNotHaveBean(EventPublisher.class); - assertThat(context).doesNotHaveBean(OtelCurrentTraceContext.class); - assertThat(context).doesNotHaveBean(OtelHttpClientHandler.class); - assertThat(context).doesNotHaveBean(OtelHttpServerHandler.class); - }); - } - - @Test - void shouldNotSupplyBeansIfTracerIsMissing() { - this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(OtelTracer.class)); + this.contextRunner.run((context) -> { + assertThat(context).hasSingleBean(OtelTracer.class); + assertThat(context).hasSingleBean(EventPublisher.class); + assertThat(context).hasSingleBean(OtelCurrentTraceContext.class); + assertThat(context).hasSingleBean(OtelHttpClientHandler.class); + assertThat(context).hasSingleBean(OtelHttpServerHandler.class); + assertThat(context).hasSingleBean(OpenTelemetry.class); + assertThat(context).hasSingleBean(SdkTracerProvider.class); + assertThat(context).hasSingleBean(ContextPropagators.class); + assertThat(context).hasSingleBean(Sampler.class); + assertThat(context).hasSingleBean(SpanProcessor.class); + assertThat(context).hasSingleBean(Tracer.class); + }); } - @Test - void shouldNotSupplyBeansIfOpenTelemetryIsMissing() { - this.contextRunner.withUserConfiguration(TracerConfiguration.class).run((context) -> { + @ParameterizedTest + @ValueSource(strings = { "io.micrometer.tracing.otel", "io.opentelemetry.sdk", "io.opentelemetry.api" }) + void shouldNotSupplyBeansIfDependencyIsMissing(String packageName) { + this.contextRunner.withClassLoader(new FilteredClassLoader(packageName)).run((context) -> { + assertThat(context).doesNotHaveBean(OtelTracer.class); + assertThat(context).doesNotHaveBean(EventPublisher.class); + assertThat(context).doesNotHaveBean(OtelCurrentTraceContext.class); assertThat(context).doesNotHaveBean(OtelHttpClientHandler.class); assertThat(context).doesNotHaveBean(OtelHttpServerHandler.class); + assertThat(context).doesNotHaveBean(OpenTelemetry.class); + assertThat(context).doesNotHaveBean(SdkTracerProvider.class); + assertThat(context).doesNotHaveBean(ContextPropagators.class); + assertThat(context).doesNotHaveBean(Sampler.class); + assertThat(context).doesNotHaveBean(SpanProcessor.class); + assertThat(context).doesNotHaveBean(Tracer.class); }); } @@ -96,6 +99,18 @@ class OpenTelemetryConfigurationsMicrometerConfigurationTests { assertThat(context).hasSingleBean(OtelHttpClientHandler.class); assertThat(context).hasBean("customOtelHttpServerHandler"); assertThat(context).hasSingleBean(OtelHttpServerHandler.class); + assertThat(context).hasBean("customOpenTelemetry"); + assertThat(context).hasSingleBean(OpenTelemetry.class); + assertThat(context).hasBean("customSdkTracerProvider"); + assertThat(context).hasSingleBean(SdkTracerProvider.class); + assertThat(context).hasBean("customContextPropagators"); + assertThat(context).hasSingleBean(ContextPropagators.class); + assertThat(context).hasBean("customSampler"); + assertThat(context).hasSingleBean(Sampler.class); + assertThat(context).hasBean("customSpanProcessor"); + assertThat(context).hasSingleBean(SpanProcessor.class); + assertThat(context).hasBean("customTracer"); + assertThat(context).hasSingleBean(Tracer.class); }); } @@ -127,24 +142,34 @@ class OpenTelemetryConfigurationsMicrometerConfigurationTests { return mock(OtelHttpServerHandler.class); } - } + @Bean + OpenTelemetry customOpenTelemetry() { + return mock(OpenTelemetry.class); + } - @Configuration(proxyBeanMethods = false) - private static class TracerConfiguration { + @Bean + SdkTracerProvider customSdkTracerProvider() { + return SdkTracerProvider.builder().build(); + } @Bean - Tracer tracer() { - return mock(Tracer.class); + ContextPropagators customContextPropagators() { + return mock(ContextPropagators.class); } - } + @Bean + Sampler customSampler() { + return mock(Sampler.class); + } - @Configuration(proxyBeanMethods = false) - private static class OpenTelemetryConfiguration { + @Bean + SpanProcessor customSpanProcessor() { + return mock(SpanProcessor.class); + } @Bean - OpenTelemetry openTelemetry() { - return mock(OpenTelemetry.class, Answers.RETURNS_MOCKS); + Tracer customTracer() { + return mock(Tracer.class); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsSdkConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsSdkConfigurationTests.java deleted file mode 100644 index 10d667554a..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsSdkConfigurationTests.java +++ /dev/null @@ -1,112 +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.actuate.autoconfigure.tracing; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.samplers.Sampler; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.SdkConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link SdkConfiguration}. - * - * @author Moritz Halbritter - */ -class OpenTelemetryConfigurationsSdkConfigurationTests { - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(SdkConfiguration.class)); - - @Test - void shouldSupplyBeans() { - this.contextRunner.run((context) -> { - assertThat(context).hasSingleBean(OpenTelemetry.class); - assertThat(context).hasSingleBean(SdkTracerProvider.class); - assertThat(context).hasSingleBean(ContextPropagators.class); - assertThat(context).hasSingleBean(Sampler.class); - assertThat(context).hasSingleBean(SpanProcessor.class); - }); - } - - @Test - void shouldBackOffOnCustomBeans() { - this.contextRunner.withUserConfiguration(CustomBeans.class).run((context) -> { - assertThat(context).hasBean("customOpenTelemetry"); - assertThat(context).hasSingleBean(OpenTelemetry.class); - assertThat(context).hasBean("customSdkTracerProvider"); - assertThat(context).hasSingleBean(SdkTracerProvider.class); - assertThat(context).hasBean("customContextPropagators"); - assertThat(context).hasSingleBean(ContextPropagators.class); - assertThat(context).hasBean("customSampler"); - assertThat(context).hasSingleBean(Sampler.class); - assertThat(context).hasBean("customSpanProcessor"); - assertThat(context).hasSingleBean(SpanProcessor.class); - }); - } - - @Test - void shouldNotSupplyBeansIfSdkIsMissing() { - this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.sdk")).run((context) -> { - assertThat(context).doesNotHaveBean(OpenTelemetry.class); - assertThat(context).doesNotHaveBean(SdkTracerProvider.class); - assertThat(context).doesNotHaveBean(ContextPropagators.class); - assertThat(context).doesNotHaveBean(Sampler.class); - assertThat(context).doesNotHaveBean(SpanProcessor.class); - }); - } - - private static class CustomBeans { - - @Bean - OpenTelemetry customOpenTelemetry() { - return mock(OpenTelemetry.class); - } - - @Bean - SdkTracerProvider customSdkTracerProvider() { - return SdkTracerProvider.builder().build(); - } - - @Bean - ContextPropagators customContextPropagators() { - return mock(ContextPropagators.class); - } - - @Bean - Sampler customSampler() { - return mock(Sampler.class); - } - - @Bean - SpanProcessor customSpanProcessor() { - return mock(SpanProcessor.class); - } - - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsTracerConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsTracerConfigurationTests.java deleted file mode 100644 index b8d9197eca..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/OpenTelemetryConfigurationsTracerConfigurationTests.java +++ /dev/null @@ -1,89 +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.actuate.autoconfigure.tracing; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryConfigurations.TracerConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.FilteredClassLoader; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link TracerConfiguration}. - * - * @author Moritz Halbritter - */ -class OpenTelemetryConfigurationsTracerConfigurationTests { - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(TracerConfiguration.class)); - - @Test - void shouldSupplyBeans() { - this.contextRunner.withUserConfiguration(OpenTelemetryConfiguration.class) - .run((context) -> assertThat(context).hasSingleBean(Tracer.class)); - } - - @Test - void shouldNotSupplyBeansIfApiIsMissing() { - this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.api")) - .run((context) -> assertThat(context).doesNotHaveBean(Tracer.class)); - } - - @Test - void shouldNotSupplyTracerIfOpenTelemetryIsMissing() { - this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(Tracer.class)); - } - - @Test - void shouldBackOffOnCustomBeans() { - this.contextRunner.withUserConfiguration(OpenTelemetryConfiguration.class, CustomConfiguration.class) - .run((context) -> { - assertThat(context).hasBean("customTracer"); - assertThat(context).hasSingleBean(Tracer.class); - }); - } - - @Configuration(proxyBeanMethods = false) - private static class OpenTelemetryConfiguration { - - @Bean - OpenTelemetry openTelemetry() { - return mock(OpenTelemetry.class); - } - - } - - @Configuration(proxyBeanMethods = false) - private static class CustomConfiguration { - - @Bean - Tracer customTracer() { - return mock(Tracer.class); - } - - } - -}