Skip to content

Commit dd7fd4b

Browse files
Add rate‑limited log warning when BatchSpanProcessor drops spans (#8167)
1 parent a88681a commit dd7fd4b

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ private static final class Worker implements Runnable {
184184
private volatile boolean continueWork = true;
185185
private final ArrayList<SpanData> batch;
186186
private final long maxQueueSize;
187+
private final AtomicInteger droppedSpanCount = new AtomicInteger(0);
187188

188189
private Worker(
189190
SpanExporter spanExporter,
@@ -212,6 +213,7 @@ private void addSpan(ReadableSpan span) {
212213
spanProcessorInstrumentation.buildQueueMetricsOnce(maxQueueSize, queue::size);
213214
if (!queue.offer(span)) {
214215
spanProcessorInstrumentation.dropSpans(1);
216+
droppedSpanCount.incrementAndGet();
215217
} else {
216218
if (queueSize.incrementAndGet() >= spansNeeded.get()) {
217219
signal.offer(true);
@@ -315,6 +317,18 @@ private void exportCurrentBatch() {
315317
return;
316318
}
317319

320+
int dropped = droppedSpanCount.getAndSet(0);
321+
if (dropped > 0) {
322+
logger.log(
323+
Level.WARNING,
324+
"BatchSpanProcessor dropped "
325+
+ dropped
326+
+ " span(s) since the last export because the queue is full"
327+
+ " (maxQueueSize="
328+
+ maxQueueSize
329+
+ ")");
330+
}
331+
318332
String error = null;
319333
try {
320334
CompletableResultCode result = spanExporter.export(Collections.unmodifiableList(batch));

sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.mockito.Mockito.verify;
1919
import static org.mockito.Mockito.when;
2020

21+
import io.github.netmikey.logunit.api.LogCapturer;
2122
import io.opentelemetry.api.internal.GuardedBy;
2223
import io.opentelemetry.api.trace.Span;
2324
import io.opentelemetry.api.trace.Tracer;
@@ -42,11 +43,13 @@
4243
import org.junit.jupiter.api.Test;
4344
import org.junit.jupiter.api.Timeout;
4445
import org.junit.jupiter.api.extension.ExtendWith;
46+
import org.junit.jupiter.api.extension.RegisterExtension;
4547
import org.mockito.ArgumentMatchers;
4648
import org.mockito.Mock;
4749
import org.mockito.junit.jupiter.MockitoExtension;
4850
import org.mockito.junit.jupiter.MockitoSettings;
4951
import org.mockito.quality.Strictness;
52+
import org.slf4j.event.Level;
5053

5154
@SuppressWarnings("PreferJavaTimeOverload")
5255
@ExtendWith(MockitoExtension.class)
@@ -62,9 +65,13 @@ class BatchSpanProcessorTest {
6265
@Mock private Sampler mockSampler;
6366
@Mock private SpanExporter mockSpanExporter;
6467

68+
@RegisterExtension
69+
LogCapturer logs = LogCapturer.create().captureForType(BatchSpanProcessor.class);
70+
6571
@BeforeEach
6672
void setUp() {
6773
when(mockSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess());
74+
when(mockSpanExporter.export(anyList())).thenReturn(CompletableResultCode.ofSuccess());
6875
}
6976

7077
@AfterEach
@@ -232,6 +239,32 @@ void exportMoreSpansThanTheBufferSize() {
232239
span6.toSpanData()));
233240
}
234241

242+
@Test
243+
void droppedSpanIsLogged() {
244+
sdkTracerProvider =
245+
SdkTracerProvider.builder()
246+
.addSpanProcessor(
247+
BatchSpanProcessor.builder(mockSpanExporter)
248+
.setMaxQueueSize(1)
249+
.setMaxExportBatchSize(1_000)
250+
.setScheduleDelay(Duration.ofDays(1))
251+
.build())
252+
.build();
253+
254+
// Fill the queue with the first span, then drop 2 more.
255+
createEndedSpan(SPAN_NAME_1);
256+
createEndedSpan(SPAN_NAME_2);
257+
createEndedSpan(SPAN_NAME_2);
258+
259+
// Force export to trigger the drop count log.
260+
sdkTracerProvider.forceFlush().join(10, TimeUnit.SECONDS);
261+
262+
logs.assertContains(
263+
loggingEvent -> loggingEvent.getLevel().equals(Level.WARN),
264+
"BatchSpanProcessor dropped 2 span(s) since the last export"
265+
+ " because the queue is full (maxQueueSize=1)");
266+
}
267+
235268
@Test
236269
void forceExport() {
237270
WaitingSpanExporter waitingSpanExporter =

0 commit comments

Comments
 (0)