Skip to content

Commit 107dd00

Browse files
committed
Separate Zipkin tracing auto-configuration
Issue: 46148
1 parent 611a600 commit 107dd00

File tree

7 files changed

+129
-183
lines changed

7 files changed

+129
-183
lines changed

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

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,31 @@
1616

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

19+
import java.net.http.HttpClient;
20+
import java.net.http.HttpClient.Builder;
21+
22+
import zipkin2.reporter.BytesMessageSender;
1923
import zipkin2.reporter.Encoding;
24+
import zipkin2.reporter.HttpEndpointSupplier;
25+
import zipkin2.reporter.HttpEndpointSuppliers;
2026

21-
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration;
22-
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration;
23-
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.SenderConfiguration;
24-
import org.springframework.boot.autoconfigure.AutoConfiguration;
27+
import org.springframework.beans.factory.ObjectProvider;
2528
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2629
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2730
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2831
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2932
import org.springframework.context.annotation.Bean;
30-
import org.springframework.context.annotation.Import;
3133

3234
/**
3335
* {@link EnableAutoConfiguration Auto-configuration} for Zipkin.
34-
* <p>
35-
* It uses imports on {@link ZipkinConfigurations} to guarantee the correct configuration
36-
* ordering.
3736
*
3837
* @author Moritz Halbritter
38+
* @author Moritz Halbritter
39+
* @author Stefan Bratanov
40+
* @author Wick Dynex
3941
* @since 3.0.0
4042
*/
41-
@AutoConfiguration(afterName = "org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration")
4243
@ConditionalOnClass(Encoding.class)
43-
@Import({ SenderConfiguration.class, BraveConfiguration.class, OpenTelemetryConfiguration.class })
4444
@EnableConfigurationProperties(ZipkinProperties.class)
4545
public class ZipkinAutoConfiguration {
4646

@@ -59,4 +59,21 @@ Encoding encoding(ZipkinProperties properties) {
5959
};
6060
}
6161

62+
@Bean
63+
@ConditionalOnMissingBean(BytesMessageSender.class)
64+
@ConditionalOnClass(HttpClient.class)
65+
ZipkinHttpClientSender httpClientSender(ZipkinProperties properties, Encoding encoding,
66+
ObjectProvider<ZipkinHttpClientBuilderCustomizer> customizers,
67+
ObjectProvider<ZipkinConnectionDetails> connectionDetailsProvider,
68+
ObjectProvider<HttpEndpointSupplier.Factory> endpointSupplierFactoryProvider) {
69+
ZipkinConnectionDetails connectionDetails = connectionDetailsProvider
70+
.getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties));
71+
HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider
72+
.getIfAvailable(HttpEndpointSuppliers::constantFactory);
73+
Builder httpClientBuilder = HttpClient.newBuilder().connectTimeout(properties.getConnectTimeout());
74+
customizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder));
75+
return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(),
76+
httpClientBuilder.build(), properties.getReadTimeout());
77+
}
78+
6279
}
Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

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

19-
import java.net.http.HttpClient;
20-
import java.net.http.HttpClient.Builder;
21-
2219
import brave.Tag;
2320
import brave.Tags;
2421
import brave.handler.MutableSpan;
@@ -27,59 +24,36 @@
2724
import zipkin2.reporter.BytesEncoder;
2825
import zipkin2.reporter.BytesMessageSender;
2926
import zipkin2.reporter.Encoding;
30-
import zipkin2.reporter.HttpEndpointSupplier;
31-
import zipkin2.reporter.HttpEndpointSuppliers;
3227
import zipkin2.reporter.SpanBytesEncoder;
3328
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
3429
import zipkin2.reporter.brave.MutableSpanBytesEncoder;
3530

3631
import org.springframework.beans.factory.ObjectProvider;
3732
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
33+
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinTracingAutoConfiguration.BraveConfiguration;
34+
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinTracingAutoConfiguration.OpenTelemetryConfiguration;
35+
import org.springframework.boot.autoconfigure.AutoConfiguration;
36+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3837
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3938
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
4039
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
41-
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4240
import org.springframework.context.annotation.Bean;
4341
import org.springframework.context.annotation.Configuration;
4442
import org.springframework.context.annotation.Import;
4543

4644
/**
47-
* Configurations for Zipkin. Those are imported by {@link ZipkinAutoConfiguration}.
45+
* {@link EnableAutoConfiguration Auto-configuration} for Zipkin tracing.
4846
*
4947
* @author Moritz Halbritter
5048
* @author Stefan Bratanov
5149
* @author Wick Dynex
50+
* @author Phillip Webb
51+
* @since 4.0.0
5252
*/
53-
class ZipkinConfigurations {
54-
55-
@Configuration(proxyBeanMethods = false)
56-
@Import({ HttpClientSenderConfiguration.class })
57-
static class SenderConfiguration {
58-
59-
}
60-
61-
@Configuration(proxyBeanMethods = false)
62-
@ConditionalOnClass(HttpClient.class)
63-
@EnableConfigurationProperties(ZipkinProperties.class)
64-
static class HttpClientSenderConfiguration {
65-
66-
@Bean
67-
@ConditionalOnMissingBean(BytesMessageSender.class)
68-
ZipkinHttpClientSender httpClientSender(ZipkinProperties properties, Encoding encoding,
69-
ObjectProvider<ZipkinHttpClientBuilderCustomizer> customizers,
70-
ObjectProvider<ZipkinConnectionDetails> connectionDetailsProvider,
71-
ObjectProvider<HttpEndpointSupplier.Factory> endpointSupplierFactoryProvider) {
72-
ZipkinConnectionDetails connectionDetails = connectionDetailsProvider
73-
.getIfAvailable(() -> new PropertiesZipkinConnectionDetails(properties));
74-
HttpEndpointSupplier.Factory endpointSupplierFactory = endpointSupplierFactoryProvider
75-
.getIfAvailable(HttpEndpointSuppliers::constantFactory);
76-
Builder httpClientBuilder = HttpClient.newBuilder().connectTimeout(properties.getConnectTimeout());
77-
customizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder));
78-
return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, connectionDetails.getSpanEndpoint(),
79-
httpClientBuilder.build(), properties.getReadTimeout());
80-
}
81-
82-
}
53+
@ConditionalOnClass(Encoding.class)
54+
@AutoConfiguration(afterName = "org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration")
55+
@Import({ BraveConfiguration.class, OpenTelemetryConfiguration.class })
56+
public class ZipkinTracingAutoConfiguration {
8357

8458
@Configuration(proxyBeanMethods = false)
8559
@ConditionalOnClass(AsyncZipkinSpanHandler.class)

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryTracingAutoC
6363
org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpTracingAutoConfiguration
6464
org.springframework.boot.actuate.autoconfigure.tracing.prometheus.PrometheusExemplarsAutoConfiguration
6565
org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration
66+
org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinTracingAutoConfiguration
6667
org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration
6768
org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration
6869
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration
@@ -71,4 +72,4 @@ org.springframework.boot.actuate.autoconfigure.web.server.jetty.JettyServletMana
7172
org.springframework.boot.actuate.autoconfigure.web.server.netty.NettyReactiveManagementContextAutoConfiguration
7273
org.springframework.boot.actuate.autoconfigure.web.server.undertow.UndertowReactiveManagementContextAutoConfiguration
7374
org.springframework.boot.actuate.autoconfigure.web.server.undertow.UndertowServletManagementContextAutoConfiguration
74-
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration
75+
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration

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

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

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

19+
import java.net.http.HttpClient;
20+
1921
import org.junit.jupiter.api.Test;
22+
import zipkin2.reporter.BytesMessageSender;
2023
import zipkin2.reporter.Encoding;
24+
import zipkin2.reporter.HttpEndpointSupplier;
2125

2226
import org.springframework.boot.autoconfigure.AutoConfigurations;
2327
import org.springframework.boot.test.context.FilteredClassLoader;
@@ -26,11 +30,13 @@
2630
import org.springframework.context.annotation.Configuration;
2731

2832
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.mockito.Mockito.mock;
2934

3035
/**
3136
* Tests for {@link ZipkinAutoConfiguration}.
3237
*
3338
* @author Moritz Halbritter
39+
* @author Wick Dynex
3440
*/
3541
class ZipkinAutoConfigurationTests {
3642

@@ -39,8 +45,12 @@ class ZipkinAutoConfigurationTests {
3945

4046
@Test
4147
void shouldSupplyBeans() {
42-
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(Encoding.class)
43-
.hasSingleBean(PropertiesZipkinConnectionDetails.class));
48+
this.contextRunner.run((context) -> {
49+
assertThat(context).hasSingleBean(Encoding.class);
50+
assertThat(context).hasSingleBean(PropertiesZipkinConnectionDetails.class);
51+
assertThat(context).hasSingleBean(BytesMessageSender.class);
52+
assertThat(context).hasSingleBean(ZipkinHttpClientSender.class);
53+
});
4454
}
4555

4656
@Test
@@ -50,13 +60,37 @@ void shouldNotSupplyBeansIfZipkinReporterIsMissing() {
5060
}
5161

5262
@Test
53-
void shouldBackOffOnCustomBeans() {
54-
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
63+
void shouldNotProvideHttpClientSenderIfHttpClientIsNotAvailable() {
64+
this.contextRunner.withClassLoader(new FilteredClassLoader(HttpClient.class))
65+
.run((context) -> assertThat(context).doesNotHaveBean(ZipkinHttpClientSender.class));
66+
}
67+
68+
@Test
69+
void shouldBackOffOnCustomEncodingBeans() {
70+
this.contextRunner.withUserConfiguration(CustomEncodingConfiguration.class).run((context) -> {
5571
assertThat(context).hasBean("customEncoding");
5672
assertThat(context).hasSingleBean(Encoding.class);
5773
});
5874
}
5975

76+
@Test
77+
void shouldBackOffOnCustomSenderBeans() {
78+
this.contextRunner.withUserConfiguration(CustomSenderConfiguration.class).run((context) -> {
79+
assertThat(context).hasBean("customSender");
80+
assertThat(context).hasSingleBean(BytesMessageSender.class);
81+
});
82+
}
83+
84+
@Test
85+
void shouldUseCustomHttpEndpointSupplierFactory() {
86+
this.contextRunner.withUserConfiguration(CustomHttpEndpointSupplierFactoryConfiguration.class)
87+
.run((context) -> {
88+
ZipkinHttpClientSender httpClientSender = context.getBean(ZipkinHttpClientSender.class);
89+
assertThat(httpClientSender).extracting("endpointSupplier")
90+
.isInstanceOf(CustomHttpEndpointSupplier.class);
91+
});
92+
}
93+
6094
@Test
6195
void definesPropertiesBasedConnectionDetailsByDefault() {
6296
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesZipkinConnectionDetails.class));
@@ -94,7 +128,7 @@ public String getSpanEndpoint() {
94128
}
95129

96130
@Configuration(proxyBeanMethods = false)
97-
private static final class CustomConfiguration {
131+
private static final class CustomEncodingConfiguration {
98132

99133
@Bean
100134
Encoding customEncoding() {
@@ -103,4 +137,52 @@ Encoding customEncoding() {
103137

104138
}
105139

140+
@Configuration(proxyBeanMethods = false)
141+
static class CustomSenderConfiguration {
142+
143+
@Bean
144+
BytesMessageSender customSender() {
145+
return mock(BytesMessageSender.class);
146+
}
147+
148+
}
149+
150+
@Configuration(proxyBeanMethods = false)
151+
static class CustomHttpEndpointSupplierFactoryConfiguration {
152+
153+
@Bean
154+
HttpEndpointSupplier.Factory httpEndpointSupplier() {
155+
return new CustomHttpEndpointSupplierFactory();
156+
}
157+
158+
}
159+
160+
static class CustomHttpEndpointSupplierFactory implements HttpEndpointSupplier.Factory {
161+
162+
@Override
163+
public HttpEndpointSupplier create(String endpoint) {
164+
return new CustomHttpEndpointSupplier(endpoint);
165+
}
166+
167+
}
168+
169+
static class CustomHttpEndpointSupplier implements HttpEndpointSupplier {
170+
171+
private final String endpoint;
172+
173+
CustomHttpEndpointSupplier(String endpoint) {
174+
this.endpoint = endpoint;
175+
}
176+
177+
@Override
178+
public String get() {
179+
return this.endpoint;
180+
}
181+
182+
@Override
183+
public void close() {
184+
}
185+
186+
}
187+
106188
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import zipkin2.reporter.Encoding;
2929
import zipkin2.reporter.brave.AsyncZipkinSpanHandler;
3030

31-
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.BraveConfiguration;
31+
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinTracingAutoConfiguration.BraveConfiguration;
3232
import org.springframework.boot.autoconfigure.AutoConfigurations;
3333
import org.springframework.boot.test.context.FilteredClassLoader;
3434
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import zipkin2.reporter.BytesMessageSender;
2424
import zipkin2.reporter.Encoding;
2525

26-
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration;
26+
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinTracingAutoConfiguration.OpenTelemetryConfiguration;
2727
import org.springframework.boot.autoconfigure.AutoConfigurations;
2828
import org.springframework.boot.test.context.FilteredClassLoader;
2929
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

0 commit comments

Comments
 (0)