diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbf61141d7..28fd72c8bdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - [Config] Trim whitespace on properties path ([#4880](https://github.com/getsentry/sentry-java/pull/4880)) - Only set `DefaultReplayBreadcrumbConverter` if replay is available ([#4888](https://github.com/getsentry/sentry-java/pull/4888)) - Session Replay: Cache connection status instead of using blocking calls ([#4891](https://github.com/getsentry/sentry-java/pull/4891)) +- Fix log count in client reports ([#4869](https://github.com/getsentry/sentry-java/pull/4869)) ### Improvements diff --git a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java index 4e2383eb107..7b415ce48c9 100644 --- a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java +++ b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java @@ -6,6 +6,7 @@ import io.sentry.SentryEnvelopeItem; import io.sentry.SentryItemType; import io.sentry.SentryLevel; +import io.sentry.SentryLogEvents; import io.sentry.SentryOptions; import io.sentry.protocol.SentrySpan; import io.sentry.protocol.SentryTransaction; @@ -98,9 +99,19 @@ public void recordLostEnvelopeItem( reason.getReason(), DataCategory.Span.getCategory(), spans.size() + 1L); executeOnDiscard(reason, DataCategory.Span, spans.size() + 1L); } + recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), 1L); + executeOnDiscard(reason, itemCategory, 1L); + } else if (itemCategory.equals(DataCategory.LogItem)) { + final @Nullable SentryLogEvents logs = envelopeItem.getLogs(options.getSerializer()); + if (logs != null) { + final long count = logs.getItems().size(); + recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), count); + executeOnDiscard(reason, itemCategory, count); + } + } else { + recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), 1L); + executeOnDiscard(reason, itemCategory, 1L); } - recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), 1L); - executeOnDiscard(reason, itemCategory, 1L); } } catch (Throwable e) { options.getLogger().log(SentryLevel.ERROR, e, "Unable to record lost envelope item."); diff --git a/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt b/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt index 2b34fd839b0..4316af5a2bc 100644 --- a/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt +++ b/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt @@ -16,6 +16,10 @@ import io.sentry.SentryEnvelope import io.sentry.SentryEnvelopeHeader import io.sentry.SentryEnvelopeItem import io.sentry.SentryEvent +import io.sentry.SentryLogEvent +import io.sentry.SentryLogEvents +import io.sentry.SentryLogLevel +import io.sentry.SentryLongDate import io.sentry.SentryOptions import io.sentry.SentryReplayEvent import io.sentry.SentryTracer @@ -347,6 +351,34 @@ class ClientReportTest { verify(onDiscardMock, times(1)).execute(DiscardReason.BEFORE_SEND, DataCategory.Profile, 1) } + @Test + fun `recording lost client report counts log entries`() { + val onDiscardMock = mock() + givenClientReportRecorder { options -> options.onDiscard = onDiscardMock } + + val envelope = + testHelper.newEnvelope( + SentryEnvelopeItem.fromLogs( + opts.serializer, + SentryLogEvents( + listOf( + SentryLogEvent(SentryId(), SentryLongDate(1), "log message 1", SentryLogLevel.ERROR), + SentryLogEvent(SentryId(), SentryLongDate(2), "log message 2", SentryLogLevel.WARN), + ) + ), + ) + ) + + clientReportRecorder.recordLostEnvelopeItem(DiscardReason.NETWORK_ERROR, envelope.items.first()) + + verify(onDiscardMock, times(1)).execute(DiscardReason.NETWORK_ERROR, DataCategory.LogItem, 2) + + val clientReport = clientReportRecorder.resetCountsAndGenerateClientReport() + val logItem = + clientReport!!.discardedEvents!!.first { it.category == DataCategory.LogItem.category } + assertEquals(2, logItem.quantity) + } + private fun givenClientReportRecorder( callback: Sentry.OptionsConfiguration? = null ) {