Skip to content

Commit 617244b

Browse files
committed
Merge pull request #44900 from nosan
* pr/44900: Polish "Add OTLP span exporter builder customizers" Add OTLP span exporter builder customizers Closes gh-44900
2 parents 49db6dd + f36d9a9 commit 617244b

File tree

5 files changed

+124
-2
lines changed

5 files changed

+124
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.tracing.otlp;
18+
19+
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
20+
21+
/**
22+
* Callback interface that can be implemented by beans wishing to customize the
23+
* {@link OtlpGrpcSpanExporterBuilder} whilst retaining default auto-configuration.
24+
*
25+
* @author Dmytro Nosan
26+
* @since 3.5.0
27+
*/
28+
@FunctionalInterface
29+
public interface OtlpGrpcSpanExporterBuilderCustomizer {
30+
31+
/**
32+
* Customize the {@link OtlpGrpcSpanExporterBuilder}.
33+
* @param builder the builder to customize
34+
*/
35+
void customize(OtlpGrpcSpanExporterBuilder builder);
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.tracing.otlp;
18+
19+
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
20+
21+
/**
22+
* Callback interface that can be implemented by beans wishing to customize the
23+
* {@link OtlpHttpSpanExporterBuilder} whilst retaining default auto-configuration.
24+
*
25+
* @author Dmytro Nosan
26+
* @since 3.5.0
27+
*/
28+
@FunctionalInterface
29+
public interface OtlpHttpSpanExporterBuilderCustomizer {
30+
31+
/**
32+
* Customize the {@link OtlpHttpSpanExporterBuilder}.
33+
* @param builder the builder to customize
34+
*/
35+
void customize(OtlpHttpSpanExporterBuilder builder);
36+
37+
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingConfigurations.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -83,28 +83,32 @@ static class Exporters {
8383
@Bean
8484
@ConditionalOnProperty(name = "management.otlp.tracing.transport", havingValue = "http", matchIfMissing = true)
8585
OtlpHttpSpanExporter otlpHttpSpanExporter(OtlpTracingProperties properties,
86-
OtlpTracingConnectionDetails connectionDetails, ObjectProvider<MeterProvider> meterProvider) {
86+
OtlpTracingConnectionDetails connectionDetails, ObjectProvider<MeterProvider> meterProvider,
87+
ObjectProvider<OtlpHttpSpanExporterBuilderCustomizer> customizers) {
8788
OtlpHttpSpanExporterBuilder builder = OtlpHttpSpanExporter.builder()
8889
.setEndpoint(connectionDetails.getUrl(Transport.HTTP))
8990
.setTimeout(properties.getTimeout())
9091
.setConnectTimeout(properties.getConnectTimeout())
9192
.setCompression(properties.getCompression().name().toLowerCase(Locale.ROOT));
9293
properties.getHeaders().forEach(builder::addHeader);
9394
meterProvider.ifAvailable(builder::setMeterProvider);
95+
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
9496
return builder.build();
9597
}
9698

9799
@Bean
98100
@ConditionalOnProperty(name = "management.otlp.tracing.transport", havingValue = "grpc")
99101
OtlpGrpcSpanExporter otlpGrpcSpanExporter(OtlpTracingProperties properties,
100-
OtlpTracingConnectionDetails connectionDetails, ObjectProvider<MeterProvider> meterProvider) {
102+
OtlpTracingConnectionDetails connectionDetails, ObjectProvider<MeterProvider> meterProvider,
103+
ObjectProvider<OtlpGrpcSpanExporterBuilderCustomizer> customizers) {
101104
OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder()
102105
.setEndpoint(connectionDetails.getUrl(Transport.GRPC))
103106
.setTimeout(properties.getTimeout())
104107
.setConnectTimeout(properties.getConnectTimeout())
105108
.setCompression(properties.getCompression().name().toLowerCase(Locale.ROOT));
106109
properties.getHeaders().forEach(builder::addHeader);
107110
meterProvider.ifAvailable(builder::setMeterProvider);
111+
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
108112
return builder.build();
109113
}
110114

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/otlp/OtlpTracingAutoConfigurationTests.java

+40
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

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

19+
import java.time.Duration;
1920
import java.util.List;
2021
import java.util.function.Supplier;
2122

@@ -230,6 +231,45 @@ void grpcShouldUseMeterProviderIfSet() {
230231
});
231232
}
232233

234+
@Test
235+
void shouldCustomizeHttpTransportWithOtlpHttpSpanExporterBuilderCustomizer() {
236+
Duration connectTimeout = Duration.ofMinutes(20);
237+
Duration timeout = Duration.ofMinutes(10);
238+
this.contextRunner
239+
.withBean("httpCustomizer1", OtlpHttpSpanExporterBuilderCustomizer.class,
240+
() -> (builder) -> builder.setConnectTimeout(connectTimeout))
241+
.withBean("httpCustomizer2", OtlpHttpSpanExporterBuilderCustomizer.class,
242+
() -> (builder) -> builder.setTimeout(timeout))
243+
.withPropertyValues("management.otlp.tracing.endpoint=http://localhost:4317/v1/traces")
244+
.run((context) -> {
245+
assertThat(context).hasSingleBean(OtlpHttpSpanExporter.class).hasSingleBean(SpanExporter.class);
246+
OtlpHttpSpanExporter exporter = context.getBean(OtlpHttpSpanExporter.class);
247+
assertThat(exporter).extracting("delegate.httpSender.client")
248+
.hasFieldOrPropertyWithValue("connectTimeoutMillis", (int) connectTimeout.toMillis())
249+
.hasFieldOrPropertyWithValue("callTimeoutMillis", (int) timeout.toMillis());
250+
});
251+
}
252+
253+
@Test
254+
void shouldCustomizeGrpcTransportWhenEnabledWithOtlpGrpcSpanExporterBuilderCustomizer() {
255+
Duration timeout = Duration.ofMinutes(10);
256+
Duration connectTimeout = Duration.ofMinutes(20);
257+
this.contextRunner
258+
.withBean("grpcCustomizer1", OtlpGrpcSpanExporterBuilderCustomizer.class,
259+
() -> (builder) -> builder.setConnectTimeout(connectTimeout))
260+
.withBean("grpcCustomizer2", OtlpGrpcSpanExporterBuilderCustomizer.class,
261+
() -> (builder) -> builder.setTimeout(timeout))
262+
.withPropertyValues("management.otlp.tracing.endpoint=http://localhost:4317/v1/traces",
263+
"management.otlp.tracing.transport=grpc")
264+
.run((context) -> {
265+
assertThat(context).hasSingleBean(OtlpGrpcSpanExporter.class).hasSingleBean(SpanExporter.class);
266+
OtlpGrpcSpanExporter exporter = context.getBean(OtlpGrpcSpanExporter.class);
267+
assertThat(exporter).extracting("delegate.grpcSender.client")
268+
.hasFieldOrPropertyWithValue("connectTimeoutMillis", (int) connectTimeout.toMillis())
269+
.hasFieldOrPropertyWithValue("callTimeoutMillis", (int) timeout.toMillis());
270+
});
271+
}
272+
233273
@Configuration(proxyBeanMethods = false)
234274
private static final class MeterProviderConfiguration {
235275

spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/tracing.adoc

+4
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ Tracing with OpenTelemetry and reporting using OTLP requires the following depen
150150

151151
Use the `management.otlp.tracing.*` configuration properties to configure reporting using OTLP.
152152

153+
NOTE: If you need to apply advanced customizations to OTLP span exporters, consider registering javadoc:org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpHttpSpanExporterBuilderCustomizer[] or javadoc:org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpGrpcSpanExporterBuilderCustomizer[] beans.
154+
These will be invoked before the creation of the `OtlpHttpSpanExporter` or `OtlpGrpcSpanExporter`.
155+
The customizers take precedence over anything applied by the auto-configuration.
156+
153157

154158

155159
[[actuator.micrometer-tracing.tracer-implementations.brave-zipkin]]

0 commit comments

Comments
 (0)