Require micrometer-tracing-bridge-otel to auto-configure OTel
Closes gh-32503
This commit is contained in:
parent
6cc3619675
commit
5449397463
|
|
@ -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<SpanProcessor> 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<TextMapPropagator> 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> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SpanProcessor> 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<TextMapPropagator> 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> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
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 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));
|
||||
}
|
||||
|
||||
@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,26 +142,36 @@ class OpenTelemetryConfigurationsMicrometerConfigurationTests {
|
|||
return mock(OtelHttpServerHandler.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class TracerConfiguration {
|
||||
@Bean
|
||||
OpenTelemetry customOpenTelemetry() {
|
||||
return mock(OpenTelemetry.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
Tracer tracer() {
|
||||
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);
|
||||
}
|
||||
|
||||
@Bean
|
||||
Tracer customTracer() {
|
||||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class OpenTelemetryConfiguration {
|
||||
|
||||
@Bean
|
||||
OpenTelemetry openTelemetry() {
|
||||
return mock(OpenTelemetry.class, Answers.RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue