Skip to content

Commit 44d18f5

Browse files
adinauerclaude
andauthored
fix(core): Record byte discards for event processor drops (#5718)
* fix(core): Record byte discards for event processor drops Track log and trace metric byte counts when event processors drop log or metric events. This keeps EventProcessor discard accounting aligned with before-send and queue-overflow paths. Co-Authored-By: Claude <noreply@anthropic.com> * changelog --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8a76183 commit 44d18f5

3 files changed

Lines changed: 86 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Fixes
1010

11+
- Record byte-level client reports when event processors discard logs or trace metrics ([#5718](https://github.com/getsentry/sentry-java/pull/5718))
1112
- Name the device-info caching thread `SentryDeviceInfoCache` so all threads spawned by the SDK are identifiable ([#5684](https://github.com/getsentry/sentry-java/pull/5684))
1213
- Apply byte-category rate limits to log and trace metric envelope items ([#5716](https://github.com/getsentry/sentry-java/pull/5716))
1314

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ private SentryEvent processEvent(
511511
private SentryLogEvent processLogEvent(
512512
@NotNull SentryLogEvent event, final @NotNull List<EventProcessor> eventProcessors) {
513513
for (final EventProcessor processor : eventProcessors) {
514+
final @NotNull SentryLogEvent eventBeforeProcessor = event;
514515
try {
515516
event = processor.process(event);
516517
} catch (Throwable e) {
@@ -533,6 +534,13 @@ private SentryLogEvent processLogEvent(
533534
options
534535
.getClientReportRecorder()
535536
.recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.LogItem);
537+
final long logEventNumberOfBytes =
538+
JsonSerializationUtils.byteSizeOf(
539+
options.getSerializer(), options.getLogger(), eventBeforeProcessor);
540+
options
541+
.getClientReportRecorder()
542+
.recordLostEvent(
543+
DiscardReason.EVENT_PROCESSOR, DataCategory.LogByte, logEventNumberOfBytes);
536544
break;
537545
}
538546
}
@@ -545,6 +553,7 @@ private SentryMetricsEvent processMetricsEvent(
545553
final @NotNull List<EventProcessor> eventProcessors,
546554
final @NotNull Hint hint) {
547555
for (final EventProcessor processor : eventProcessors) {
556+
final @NotNull SentryMetricsEvent eventBeforeProcessor = event;
548557
try {
549558
event = processor.process(event, hint);
550559
} catch (Throwable e) {
@@ -567,6 +576,15 @@ private SentryMetricsEvent processMetricsEvent(
567576
options
568577
.getClientReportRecorder()
569578
.recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.TraceMetric);
579+
final long metricsEventNumberOfBytes =
580+
JsonSerializationUtils.byteSizeOf(
581+
options.getSerializer(), options.getLogger(), eventBeforeProcessor);
582+
options
583+
.getClientReportRecorder()
584+
.recordLostEvent(
585+
DiscardReason.EVENT_PROCESSOR,
586+
DataCategory.TraceMetricByte,
587+
metricsEventNumberOfBytes);
570588
break;
571589
}
572590
}

sentry/src/test/java/io/sentry/SentryClientTest.kt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import io.sentry.test.injectForField
3333
import io.sentry.transport.ITransport
3434
import io.sentry.transport.ITransportGate
3535
import io.sentry.util.HintUtils
36+
import io.sentry.util.JsonSerializationUtils
3637
import java.io.ByteArrayInputStream
3738
import java.io.ByteArrayOutputStream
3839
import java.io.File
@@ -341,6 +342,39 @@ class SentryClientTest {
341342
)
342343
}
343344

345+
@Test
346+
fun `when log is dropped by event processor, log byte discard is recorded`() {
347+
val scope = createScope()
348+
val logEvent = SentryLogEvent(SentryId(), SentryNanotimeDate(), "message", SentryLogLevel.WARN)
349+
val logEventNumberOfBytes =
350+
JsonSerializationUtils.byteSizeOf(
351+
fixture.sentryOptions.serializer,
352+
fixture.sentryOptions.logger,
353+
logEvent,
354+
)
355+
scope.addEventProcessor(
356+
object : EventProcessor {
357+
override fun process(event: SentryLogEvent): SentryLogEvent? = null
358+
}
359+
)
360+
361+
val sut = fixture.getSut()
362+
sut.captureLog(logEvent, scope)
363+
364+
verify(fixture.loggerBatchProcessor, never()).add(any())
365+
assertClientReport(
366+
fixture.sentryOptions.clientReportRecorder,
367+
listOf(
368+
DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.LogItem.category, 1),
369+
DiscardedEvent(
370+
DiscardReason.EVENT_PROCESSOR.reason,
371+
DataCategory.LogByte.category,
372+
logEventNumberOfBytes,
373+
),
374+
),
375+
)
376+
}
377+
344378
@Test
345379
fun `when beforeSendLog is returns new instance, new instance is sent`() {
346380
val scope = createScope()
@@ -418,6 +452,39 @@ class SentryClientTest {
418452
)
419453
}
420454

455+
@Test
456+
fun `when metric is dropped by event processor, metric byte discard is recorded`() {
457+
val scope = createScope()
458+
val metricsEvent = SentryMetricsEvent(SentryId(), SentryNanotimeDate(), "name", "gauge", 123.0)
459+
val metricsEventNumberOfBytes =
460+
JsonSerializationUtils.byteSizeOf(
461+
fixture.sentryOptions.serializer,
462+
fixture.sentryOptions.logger,
463+
metricsEvent,
464+
)
465+
scope.addEventProcessor(
466+
object : EventProcessor {
467+
override fun process(event: SentryMetricsEvent, hint: Hint): SentryMetricsEvent? = null
468+
}
469+
)
470+
471+
val sut = fixture.getSut()
472+
sut.captureMetric(metricsEvent, scope, null)
473+
474+
verify(fixture.metricsBatchProcessor, never()).add(any())
475+
assertClientReport(
476+
fixture.sentryOptions.clientReportRecorder,
477+
listOf(
478+
DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.TraceMetric.category, 1),
479+
DiscardedEvent(
480+
DiscardReason.EVENT_PROCESSOR.reason,
481+
DataCategory.TraceMetricByte.category,
482+
metricsEventNumberOfBytes,
483+
),
484+
),
485+
)
486+
}
487+
421488
@Test
422489
fun `when beforeSendMetric is returns new instance, new instance is sent`() {
423490
val scope = createScope()

0 commit comments

Comments
 (0)