Skip to content

Commit ed4d13a

Browse files
committed
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
1 parent 5e844db commit ed4d13a

File tree

4 files changed

+57
-32
lines changed

4 files changed

+57
-32
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfiguration.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.tracing.zipkin;
1818

19-
import zipkin2.Span;
20-
import zipkin2.reporter.BytesEncoder;
2119
import zipkin2.reporter.Encoding;
22-
import zipkin2.reporter.SpanBytesEncoder;
2320

2421
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration;
2522
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration;
@@ -63,10 +60,4 @@ Encoding encoding(ZipkinProperties properties) {
6360
};
6461
}
6562

66-
@Bean
67-
@ConditionalOnMissingBean(value = Span.class, parameterizedContainer = BytesEncoder.class)
68-
BytesEncoder<Span> zipkinSpanEncoder(Encoding encoding) {
69-
return SpanBytesEncoder.forEncoding(encoding);
70-
}
71-
7263
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import zipkin2.reporter.Encoding;
3030
import zipkin2.reporter.HttpEndpointSupplier;
3131
import zipkin2.reporter.HttpEndpointSuppliers;
32+
import zipkin2.reporter.SpanBytesEncoder;
3233
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
3334
import zipkin2.reporter.brave.MutableSpanBytesEncoder;
3435
import zipkin2.reporter.urlconnection.URLConnectionSender;
@@ -177,7 +178,7 @@ static class BraveConfiguration {
177178

178179
@Bean
179180
@ConditionalOnMissingBean(value = MutableSpan.class, parameterizedContainer = BytesEncoder.class)
180-
BytesEncoder<MutableSpan> braveSpanEncoder(Encoding encoding,
181+
BytesEncoder<MutableSpan> mutableSpanBytesEncoder(Encoding encoding,
181182
ObjectProvider<Tag<Throwable>> throwableTagProvider) {
182183
Tag<Throwable> throwableTag = throwableTagProvider.getIfAvailable(() -> Tags.ERROR);
183184
return MutableSpanBytesEncoder.create(encoding, throwableTag);
@@ -188,22 +189,28 @@ BytesEncoder<MutableSpan> braveSpanEncoder(Encoding encoding,
188189
@ConditionalOnBean(BytesMessageSender.class)
189190
@ConditionalOnEnabledTracing
190191
AsyncZipkinSpanHandler asyncZipkinSpanHandler(BytesMessageSender sender,
191-
BytesEncoder<MutableSpan> braveSpanEncoder) {
192-
return AsyncZipkinSpanHandler.newBuilder(sender).build(braveSpanEncoder);
192+
BytesEncoder<MutableSpan> mutableSpanBytesEncoder) {
193+
return AsyncZipkinSpanHandler.newBuilder(sender).build(mutableSpanBytesEncoder);
193194
}
194195

195196
}
196197

197198
@Configuration(proxyBeanMethods = false)
198-
@ConditionalOnClass(ZipkinSpanExporter.class)
199+
@ConditionalOnClass({ ZipkinSpanExporter.class, Span.class })
199200
static class OpenTelemetryConfiguration {
200201

202+
@Bean
203+
@ConditionalOnMissingBean(value = Span.class, parameterizedContainer = BytesEncoder.class)
204+
BytesEncoder<Span> spanBytesEncoder(Encoding encoding) {
205+
return SpanBytesEncoder.forEncoding(encoding);
206+
}
207+
201208
@Bean
202209
@ConditionalOnMissingBean
203210
@ConditionalOnBean(BytesMessageSender.class)
204211
@ConditionalOnEnabledTracing
205-
ZipkinSpanExporter zipkinSpanExporter(BytesMessageSender sender, BytesEncoder<Span> zipkinSpanEncoder) {
206-
return ZipkinSpanExporter.builder().setSender(sender).setEncoder(zipkinSpanEncoder).build();
212+
ZipkinSpanExporter zipkinSpanExporter(BytesMessageSender sender, BytesEncoder<Span> spanBytesEncoder) {
213+
return ZipkinSpanExporter.builder().setSender(sender).setEncoder(spanBytesEncoder).build();
207214
}
208215

209216
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfigurationTests.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ class ZipkinAutoConfigurationTests {
4040
@Test
4141
void shouldSupplyBeans() {
4242
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(Encoding.class)
43-
.hasSingleBean(PropertiesZipkinConnectionDetails.class)
44-
.hasBean("zipkinSpanEncoder"));
43+
.hasSingleBean(PropertiesZipkinConnectionDetails.class));
4544
}
4645

4746
@Test
@@ -65,14 +64,8 @@ void definesPropertiesBasedConnectionDetailsByDefault() {
6564

6665
@Test
6766
void shouldUseCustomConnectionDetailsWhenDefined() {
68-
this.contextRunner.withBean(ZipkinConnectionDetails.class, () -> new ZipkinConnectionDetails() {
69-
70-
@Override
71-
public String getSpanEndpoint() {
72-
return "http://localhost";
73-
}
74-
75-
})
67+
this.contextRunner
68+
.withBean(ZipkinConnectionDetails.class, () -> new FixedZipkinConnectionDetails("http://localhost"))
7669
.run((context) -> assertThat(context).hasSingleBean(ZipkinConnectionDetails.class)
7770
.doesNotHaveBean(PropertiesZipkinConnectionDetails.class));
7871
}
@@ -85,6 +78,21 @@ void shouldWorkWithoutSenders() {
8578
.run((context) -> assertThat(context).hasNotFailed());
8679
}
8780

81+
private static final class FixedZipkinConnectionDetails implements ZipkinConnectionDetails {
82+
83+
private final String spanEndpoint;
84+
85+
private FixedZipkinConnectionDetails(String spanEndpoint) {
86+
this.spanEndpoint = spanEndpoint;
87+
}
88+
89+
@Override
90+
public String getSpanEndpoint() {
91+
return this.spanEndpoint;
92+
}
93+
94+
}
95+
8896
@Configuration(proxyBeanMethods = false)
8997
private static final class CustomConfiguration {
9098

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurationsOpenTelemetryConfigurationTests.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.context.annotation.Configuration;
3232

3333
import static org.assertj.core.api.Assertions.assertThat;
34-
import static org.mockito.Mockito.mock;
3534

3635
/**
3736
* Tests for {@link OpenTelemetryConfiguration}.
@@ -48,22 +47,40 @@ class ZipkinConfigurationsOpenTelemetryConfigurationTests {
4847

4948
@Test
5049
void shouldSupplyBeans() {
51-
this.contextRunner.withUserConfiguration(SenderConfiguration.class)
52-
.withBean(BytesEncoder.class, () -> mock(BytesEncoder.class))
53-
.run((context) -> assertThat(context).hasSingleBean(ZipkinSpanExporter.class));
50+
this.contextRunner.withUserConfiguration(SenderConfiguration.class, CustomEncoderConfiguration.class)
51+
.run((context) -> {
52+
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
53+
assertThat(context).hasBean("customSpanEncoder");
54+
});
5455
}
5556

5657
@Test
5758
void shouldNotSupplyZipkinSpanExporterIfSenderIsMissing() {
58-
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class));
59+
this.contextRunner.run((context) -> {
60+
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
61+
assertThat(context).hasBean("spanBytesEncoder");
62+
});
5963
}
6064

6165
@Test
6266
void shouldNotSupplyZipkinSpanExporterIfNotOnClasspath() {
6367
this.contextRunner.withClassLoader(new FilteredClassLoader("io.opentelemetry.exporter.zipkin"))
6468
.withUserConfiguration(SenderConfiguration.class)
65-
.run((context) -> assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class));
69+
.run((context) -> {
70+
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
71+
assertThat(context).doesNotHaveBean("spanBytesEncoder");
72+
});
73+
74+
}
6675

76+
@Test
77+
void shouldBackOffIfZipkinIsNotOnClasspath() {
78+
this.contextRunner.withClassLoader(new FilteredClassLoader("zipkin2.Span"))
79+
.withUserConfiguration(SenderConfiguration.class)
80+
.run((context) -> {
81+
assertThat(context).doesNotHaveBean(ZipkinSpanExporter.class);
82+
assertThat(context).doesNotHaveBean("spanBytesEncoder");
83+
});
6784
}
6885

6986
@Test
@@ -85,6 +102,7 @@ void shouldUseCustomEncoderBean() {
85102
this.contextRunner.withUserConfiguration(SenderConfiguration.class, CustomEncoderConfiguration.class)
86103
.run((context) -> {
87104
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
105+
assertThat(context).hasBean("customSpanEncoder");
88106
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
89107
.isInstanceOf(CustomSpanEncoder.class)
90108
.extracting("encoding")
@@ -99,6 +117,7 @@ void shouldUseCustomEncodingBean() {
99117
CustomEncoderConfiguration.class)
100118
.run((context) -> {
101119
assertThat(context).hasSingleBean(ZipkinSpanExporter.class);
120+
assertThat(context).hasBean("customSpanEncoder");
102121
assertThat(context.getBean(ZipkinSpanExporter.class)).extracting("encoder")
103122
.isInstanceOf(CustomSpanEncoder.class)
104123
.extracting("encoding")
@@ -140,7 +159,7 @@ ZipkinSpanExporter customZipkinSpanExporter() {
140159
private static final class CustomEncoderConfiguration {
141160

142161
@Bean
143-
BytesEncoder<Span> encoder(Encoding encoding) {
162+
BytesEncoder<Span> customSpanEncoder(Encoding encoding) {
144163
return new CustomSpanEncoder(encoding);
145164
}
146165

0 commit comments

Comments
 (0)