Move zipkin.Span types in the OpenTelemetry auto-configuration
Brave can work without zipkin2 on the classpath, OpenTelemetry can't. To not force users to have zipkin2 on the classpath, move it into the OpenTelemetry auto-configuration. See gh-39049
This commit is contained in:
parent
5e844dbbdd
commit
ed4d13a8bf
|
@ -16,10 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.tracing.zipkin;
|
package org.springframework.boot.actuate.autoconfigure.tracing.zipkin;
|
||||||
|
|
||||||
import zipkin2.Span;
|
|
||||||
import zipkin2.reporter.BytesEncoder;
|
|
||||||
import zipkin2.reporter.Encoding;
|
import zipkin2.reporter.Encoding;
|
||||||
import zipkin2.reporter.SpanBytesEncoder;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration;
|
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.OpenTelemetryConfiguration;
|
||||||
|
@ -63,10 +60,4 @@ public class ZipkinAutoConfiguration {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(value = Span.class, parameterizedContainer = BytesEncoder.class)
|
|
||||||
BytesEncoder<Span> zipkinSpanEncoder(Encoding encoding) {
|
|
||||||
return SpanBytesEncoder.forEncoding(encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import zipkin2.reporter.BytesMessageSender;
|
||||||
import zipkin2.reporter.Encoding;
|
import zipkin2.reporter.Encoding;
|
||||||
import zipkin2.reporter.HttpEndpointSupplier;
|
import zipkin2.reporter.HttpEndpointSupplier;
|
||||||
import zipkin2.reporter.HttpEndpointSuppliers;
|
import zipkin2.reporter.HttpEndpointSuppliers;
|
||||||
|
import zipkin2.reporter.SpanBytesEncoder;
|
||||||
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
|
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
|
||||||
import zipkin2.reporter.brave.MutableSpanBytesEncoder;
|
import zipkin2.reporter.brave.MutableSpanBytesEncoder;
|
||||||
import zipkin2.reporter.urlconnection.URLConnectionSender;
|
import zipkin2.reporter.urlconnection.URLConnectionSender;
|
||||||
|
@ -177,7 +178,7 @@ class ZipkinConfigurations {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(value = MutableSpan.class, parameterizedContainer = BytesEncoder.class)
|
@ConditionalOnMissingBean(value = MutableSpan.class, parameterizedContainer = BytesEncoder.class)
|
||||||
BytesEncoder<MutableSpan> braveSpanEncoder(Encoding encoding,
|
BytesEncoder<MutableSpan> mutableSpanBytesEncoder(Encoding encoding,
|
||||||
ObjectProvider<Tag<Throwable>> throwableTagProvider) {
|
ObjectProvider<Tag<Throwable>> throwableTagProvider) {
|
||||||
Tag<Throwable> throwableTag = throwableTagProvider.getIfAvailable(() -> Tags.ERROR);
|
Tag<Throwable> throwableTag = throwableTagProvider.getIfAvailable(() -> Tags.ERROR);
|
||||||
return MutableSpanBytesEncoder.create(encoding, throwableTag);
|
return MutableSpanBytesEncoder.create(encoding, throwableTag);
|
||||||
|
@ -188,22 +189,28 @@ class ZipkinConfigurations {
|
||||||
@ConditionalOnBean(BytesMessageSender.class)
|
@ConditionalOnBean(BytesMessageSender.class)
|
||||||
@ConditionalOnEnabledTracing
|
@ConditionalOnEnabledTracing
|
||||||
AsyncZipkinSpanHandler asyncZipkinSpanHandler(BytesMessageSender sender,
|
AsyncZipkinSpanHandler asyncZipkinSpanHandler(BytesMessageSender sender,
|
||||||
BytesEncoder<MutableSpan> braveSpanEncoder) {
|
BytesEncoder<MutableSpan> mutableSpanBytesEncoder) {
|
||||||
return AsyncZipkinSpanHandler.newBuilder(sender).build(braveSpanEncoder);
|
return AsyncZipkinSpanHandler.newBuilder(sender).build(mutableSpanBytesEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ConditionalOnClass(ZipkinSpanExporter.class)
|
@ConditionalOnClass({ ZipkinSpanExporter.class, Span.class })
|
||||||
static class OpenTelemetryConfiguration {
|
static class OpenTelemetryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(value = Span.class, parameterizedContainer = BytesEncoder.class)
|
||||||
|
BytesEncoder<Span> spanBytesEncoder(Encoding encoding) {
|
||||||
|
return SpanBytesEncoder.forEncoding(encoding);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnBean(BytesMessageSender.class)
|
@ConditionalOnBean(BytesMessageSender.class)
|
||||||
@ConditionalOnEnabledTracing
|
@ConditionalOnEnabledTracing
|
||||||
ZipkinSpanExporter zipkinSpanExporter(BytesMessageSender sender, BytesEncoder<Span> zipkinSpanEncoder) {
|
ZipkinSpanExporter zipkinSpanExporter(BytesMessageSender sender, BytesEncoder<Span> spanBytesEncoder) {
|
||||||
return ZipkinSpanExporter.builder().setSender(sender).setEncoder(zipkinSpanEncoder).build();
|
return ZipkinSpanExporter.builder().setSender(sender).setEncoder(spanBytesEncoder).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,7 @@ class ZipkinAutoConfigurationTests {
|
||||||
@Test
|
@Test
|
||||||
void shouldSupplyBeans() {
|
void shouldSupplyBeans() {
|
||||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(Encoding.class)
|
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(Encoding.class)
|
||||||
.hasSingleBean(PropertiesZipkinConnectionDetails.class)
|
.hasSingleBean(PropertiesZipkinConnectionDetails.class));
|
||||||
.hasBean("zipkinSpanEncoder"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -65,14 +64,8 @@ class ZipkinAutoConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||||
this.contextRunner.withBean(ZipkinConnectionDetails.class, () -> new ZipkinConnectionDetails() {
|
this.contextRunner
|
||||||
|
.withBean(ZipkinConnectionDetails.class, () -> new FixedZipkinConnectionDetails("http://localhost"))
|
||||||
@Override
|
|
||||||
public String getSpanEndpoint() {
|
|
||||||
return "http://localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ZipkinConnectionDetails.class)
|
.run((context) -> assertThat(context).hasSingleBean(ZipkinConnectionDetails.class)
|
||||||
.doesNotHaveBean(PropertiesZipkinConnectionDetails.class));
|
.doesNotHaveBean(PropertiesZipkinConnectionDetails.class));
|
||||||
}
|
}
|
||||||
|
@ -85,6 +78,21 @@ class ZipkinAutoConfigurationTests {
|
||||||
.run((context) -> assertThat(context).hasNotFailed());
|
.run((context) -> assertThat(context).hasNotFailed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class FixedZipkinConnectionDetails implements ZipkinConnectionDetails {
|
||||||
|
|
||||||
|
private final String spanEndpoint;
|
||||||
|
|
||||||
|
private FixedZipkinConnectionDetails(String spanEndpoint) {
|
||||||
|
this.spanEndpoint = spanEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSpanEndpoint() {
|
||||||
|
return this.spanEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
private static final class CustomConfiguration {
|
private static final class CustomConfiguration {
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link OpenTelemetryConfiguration}.
|
* Tests for {@link OpenTelemetryConfiguration}.
|
||||||
|
@ -48,24 +47,42 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldSupplyBeans() {
|
void shouldSupplyBeans() {
|
||||||
this.contextRunner.withUserConfiguration(SenderConfiguration.class)
|
this.contextRunner.withUserConfiguration(SenderConfiguration.class, CustomEncoderConfiguration.class)
|
||||||
.withBean(BytesEncoder.class, () -> mock(BytesEncoder.class))
|
.run((context) -> {
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ZipkinSpanExporter.class));
|
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).hasBean("customSpanEncoder");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotSupplyZipkinSpanExporterIfSenderIsMissing() {
|
void shouldNotSupplyZipkinSpanExporterIfSenderIsMissing() {
|
||||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class));
|
this.contextRunner.run((context) -> {
|
||||||
|
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).hasBean("spanBytesEncoder");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldNotSupplyZipkinSpanExporterIfNotOnClasspath() {
|
void shouldNotSupplyZipkinSpanExporterIfNotOnClasspath() {
|
||||||
this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.exporter.zipkin"))
|
this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.exporter.zipkin"))
|
||||||
.withUserConfiguration(SenderConfiguration.class)
|
.withUserConfiguration(SenderConfiguration.class)
|
||||||
.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class));
|
.run((context) -> {
|
||||||
|
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).doesNotHaveBean("spanBytesEncoder");
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBackOffIfZipkinIsNotOnClasspath() {
|
||||||
|
this.contextRunner.withClassLoader(new FilteredClassLoader("zipkin2.Span"))
|
||||||
|
.withUserConfiguration(SenderConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).doesNotHaveBean("spanBytesEncoder");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldBackOffOnCustomBeans() {
|
void shouldBackOffOnCustomBeans() {
|
||||||
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
|
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
|
||||||
|
@ -85,6 +102,7 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
|
||||||
this.contextRunner.withUserConfiguration(SenderConfiguration.class, CustomEncoderConfiguration.class)
|
this.contextRunner.withUserConfiguration(SenderConfiguration.class, CustomEncoderConfiguration.class)
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
|
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).hasBean("customSpanEncoder");
|
||||||
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
|
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
|
||||||
.isInstanceOf(CustomSpanEncoder.class)
|
.isInstanceOf(CustomSpanEncoder.class)
|
||||||
.extracting("encoding")
|
.extracting("encoding")
|
||||||
|
@ -99,6 +117,7 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
|
||||||
CustomEncoderConfiguration.class)
|
CustomEncoderConfiguration.class)
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
|
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
|
||||||
|
assertThat(context).hasBean("customSpanEncoder");
|
||||||
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
|
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
|
||||||
.isInstanceOf(CustomSpanEncoder.class)
|
.isInstanceOf(CustomSpanEncoder.class)
|
||||||
.extracting("encoding")
|
.extracting("encoding")
|
||||||
|
@ -140,7 +159,7 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
|
||||||
private static final class CustomEncoderConfiguration {
|
private static final class CustomEncoderConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
BytesEncoder<Span> encoder(Encoding encoding) {
|
BytesEncoder<Span> customSpanEncoder(Encoding encoding) {
|
||||||
return new CustomSpanEncoder(encoding);
|
return new CustomSpanEncoder(encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue