Skip to content

Commit 2bd37a6

Browse files
committed
Introduce properties for configuring the OpenTelemetry BatchSpanProcessor
This commit adds the following properties to allow customization of the BatchSpanProcessor: - management.tracing.opentelemetry.batch-span-processor.export-unsampled-spans - management.tracing.opentelemetry.batch-span-processor.exporter-timeout - management.tracing.opentelemetry.batch-span-processor.max-export-batch-size - management.tracing.opentelemetry.batch-span-processor.max-queue-size - management.tracing.opentelemetry.batch-span-processor.schedule-delay Default values were taken from BatchSpanProcessorBuilder. Signed-off-by: Dmytro Nosan <dimanosan@gmail.com>
1 parent 207c8f5 commit 2bd37a6

File tree

3 files changed

+144
-4
lines changed

3 files changed

+144
-4
lines changed

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

+11-3
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,17 @@ SpanProcessors spanProcessors(ObjectProvider<SpanProcessor> spanProcessors) {
119119
BatchSpanProcessor otelSpanProcessor(SpanExporters spanExporters,
120120
ObjectProvider<SpanExportingPredicate> spanExportingPredicates, ObjectProvider<SpanReporter> spanReporters,
121121
ObjectProvider<SpanFilter> spanFilters, ObjectProvider<MeterProvider> meterProvider) {
122-
BatchSpanProcessorBuilder builder = BatchSpanProcessor
123-
.builder(new CompositeSpanExporter(spanExporters.list(), spanExportingPredicates.orderedStream().toList(),
124-
spanReporters.orderedStream().toList(), spanFilters.orderedStream().toList()));
122+
TracingProperties.OpenTelemetry.BatchSpanProcessor properties = this.tracingProperties.getOpentelemetry()
123+
.getBatchSpanProcessor();
124+
CompositeSpanExporter spanExporter = new CompositeSpanExporter(spanExporters.list(),
125+
spanExportingPredicates.orderedStream().toList(), spanReporters.orderedStream().toList(),
126+
spanFilters.orderedStream().toList());
127+
BatchSpanProcessorBuilder builder = BatchSpanProcessor.builder(spanExporter)
128+
.setExporterTimeout(properties.getExporterTimeout())
129+
.setExportUnsampledSpans(properties.isExportUnsampledSpans())
130+
.setMaxExportBatchSize(properties.getMaxExportBatchSize())
131+
.setMaxQueueSize(properties.getMaxQueueSize())
132+
.setScheduleDelay(properties.getScheduleDelay());
125133
meterProvider.ifAvailable(builder::setMeterProvider);
126134
return builder.build();
127135
}

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

+94-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

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

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

@@ -51,6 +52,11 @@ public class TracingProperties {
5152
*/
5253
private final Brave brave = new Brave();
5354

55+
/**
56+
* OpenTelemetry configuration.
57+
*/
58+
private final OpenTelemetry opentelemetry = new OpenTelemetry();
59+
5460
public Sampling getSampling() {
5561
return this.sampling;
5662
}
@@ -67,6 +73,10 @@ public Brave getBrave() {
6773
return this.brave;
6874
}
6975

76+
public OpenTelemetry getOpentelemetry() {
77+
return this.opentelemetry;
78+
}
79+
7080
public static class Sampling {
7181

7282
/**
@@ -293,4 +303,87 @@ public void setSpanJoiningSupported(boolean spanJoiningSupported) {
293303

294304
}
295305

306+
public static class OpenTelemetry {
307+
308+
/**
309+
* Batch Span Processor configuration.
310+
*/
311+
private final BatchSpanProcessor batchSpanProcessor = new BatchSpanProcessor();
312+
313+
public BatchSpanProcessor getBatchSpanProcessor() {
314+
return this.batchSpanProcessor;
315+
}
316+
317+
public static class BatchSpanProcessor {
318+
319+
/**
320+
* Whether unsampled spans should be exported.
321+
*/
322+
private boolean exportUnsampledSpans;
323+
324+
/**
325+
* Maximum time an export will be allowed to run before being cancelled.
326+
*/
327+
private Duration exporterTimeout = Duration.ofSeconds(30);
328+
329+
/**
330+
* Maximum batch size for each export. This must be less than or equal to
331+
* maxQueueSize.
332+
*/
333+
private int maxExportBatchSize = 512;
334+
335+
/**
336+
* Maximum number of Spans that are kept in the queue before start dropping.
337+
*/
338+
private int maxQueueSize = 2048;
339+
340+
/**
341+
* The delay interval between two consecutive exports.
342+
*/
343+
private Duration scheduleDelay = Duration.ofSeconds(5);
344+
345+
public boolean isExportUnsampledSpans() {
346+
return this.exportUnsampledSpans;
347+
}
348+
349+
public void setExportUnsampledSpans(boolean exportUnsampledSpans) {
350+
this.exportUnsampledSpans = exportUnsampledSpans;
351+
}
352+
353+
public Duration getExporterTimeout() {
354+
return this.exporterTimeout;
355+
}
356+
357+
public void setExporterTimeout(Duration exporterTimeout) {
358+
this.exporterTimeout = exporterTimeout;
359+
}
360+
361+
public int getMaxExportBatchSize() {
362+
return this.maxExportBatchSize;
363+
}
364+
365+
public void setMaxExportBatchSize(int maxExportBatchSize) {
366+
this.maxExportBatchSize = maxExportBatchSize;
367+
}
368+
369+
public int getMaxQueueSize() {
370+
return this.maxQueueSize;
371+
}
372+
373+
public void setMaxQueueSize(int maxQueueSize) {
374+
this.maxQueueSize = maxQueueSize;
375+
}
376+
377+
public Duration getScheduleDelay() {
378+
return this.scheduleDelay;
379+
}
380+
381+
public void setScheduleDelay(Duration scheduleDelay) {
382+
this.scheduleDelay = scheduleDelay;
383+
}
384+
385+
}
386+
387+
}
388+
296389
}

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

+39
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.springframework.context.annotation.Bean;
7171
import org.springframework.context.annotation.Configuration;
7272
import org.springframework.core.annotation.Order;
73+
import org.springframework.test.util.ReflectionTestUtils;
7374

7475
import static org.assertj.core.api.Assertions.assertThat;
7576
import static org.assertj.core.api.Assertions.fail;
@@ -324,6 +325,44 @@ void shouldDisablePropagationIfTracingIsDisabled() {
324325
});
325326
}
326327

328+
@Test
329+
void batchSpanProcessorShouldBeConfiguredWithCustomProperties() {
330+
this.contextRunner
331+
.withPropertyValues("management.tracing.opentelemetry.batch-span-processor.exporter-timeout=45s",
332+
"management.tracing.opentelemetry.batch-span-processor.export-unsampled-spans=true",
333+
"management.tracing.opentelemetry.batch-span-processor.max-export-batch-size=256",
334+
"management.tracing.opentelemetry.batch-span-processor.max-queue-size=4096",
335+
"management.tracing.opentelemetry.batch-span-processor.schedule-delay=15s")
336+
.run((context) -> {
337+
assertThat(context).hasSingleBean(BatchSpanProcessor.class);
338+
BatchSpanProcessor batchSpanProcessor = context.getBean(BatchSpanProcessor.class);
339+
assertThat(batchSpanProcessor).hasFieldOrPropertyWithValue("exportUnsampledSpans", true)
340+
.extracting("worker")
341+
.hasFieldOrPropertyWithValue("exporterTimeoutNanos", Duration.ofSeconds(45).toNanos())
342+
.hasFieldOrPropertyWithValue("maxExportBatchSize", 256)
343+
.hasFieldOrPropertyWithValue("scheduleDelayNanos", Duration.ofSeconds(15).toNanos())
344+
.extracting("queue")
345+
.satisfies((queue) -> assertThat(ReflectionTestUtils.<Integer>invokeMethod(queue, "capacity"))
346+
.isEqualTo(4096));
347+
});
348+
}
349+
350+
@Test
351+
void batchSpanProcessorShouldBeConfiguredWithDefaultProperties() {
352+
this.contextRunner.run((context) -> {
353+
assertThat(context).hasSingleBean(BatchSpanProcessor.class);
354+
BatchSpanProcessor batchSpanProcessor = context.getBean(BatchSpanProcessor.class);
355+
assertThat(batchSpanProcessor).hasFieldOrPropertyWithValue("exportUnsampledSpans", false)
356+
.extracting("worker")
357+
.hasFieldOrPropertyWithValue("exporterTimeoutNanos", Duration.ofSeconds(30).toNanos())
358+
.hasFieldOrPropertyWithValue("maxExportBatchSize", 512)
359+
.hasFieldOrPropertyWithValue("scheduleDelayNanos", Duration.ofSeconds(5).toNanos())
360+
.extracting("queue")
361+
.satisfies((queue) -> assertThat(ReflectionTestUtils.<Integer>invokeMethod(queue, "capacity"))
362+
.isEqualTo(2048));
363+
});
364+
}
365+
327366
@Test // gh-41439
328367
@ForkedClassPath
329368
void shouldPublishEventsWhenContextStorageIsInitializedEarly() {

0 commit comments

Comments
 (0)