diff --git a/CHANGELOG.md b/CHANGELOG.md index f9c5dd4e6d..e140ea669e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ } ``` +### Fixes + +- Flush logs on crash ([#4684](https://github.com/getsentry/sentry-java/pull/4684)) + ### Improvements - Remove internal API status from get/setDistinctId ([#4708](https://github.com/getsentry/sentry-java/pull/4708)) diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 998f1c5d8d..43a5a68423 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -36,6 +36,8 @@ public final class SentryClient implements ISentryClient { static final String SENTRY_PROTOCOL_VERSION = "7"; + private static final int LOG_FLUSH_ON_CRASH_TIMEOUT_MILLIS = 500; + private boolean enabled; private final @NotNull SentryOptions options; @@ -244,6 +246,11 @@ private boolean shouldApplyScopeData(final @NotNull CheckIn event, final @NotNul if (scope != null) { finalizeTransaction(scope, hint); } + // if event is backfillable or cached, it's an event from the past. + // Otherwise, we want to flush logs, as we encountered a crash. + if (event != null && !isBackfillable && !isCached && event.isCrashed()) { + loggerBatchProcessor.flush(LOG_FLUSH_ON_CRASH_TIMEOUT_MILLIS); + } return sentryId; } diff --git a/sentry/src/test/java/io/sentry/SentryClientTest.kt b/sentry/src/test/java/io/sentry/SentryClientTest.kt index 878eb2d4aa..c45dd1002f 100644 --- a/sentry/src/test/java/io/sentry/SentryClientTest.kt +++ b/sentry/src/test/java/io/sentry/SentryClientTest.kt @@ -3023,6 +3023,25 @@ class SentryClientTest { assertTrue(terminated == true) } + @Test + fun `flush logs for crash events`() { + val sut = fixture.getSut() + val batchProcessor = mock() + sut.injectForField("loggerBatchProcessor", batchProcessor) + sut.captureLog( + SentryLogEvent(SentryId(), SentryNanotimeDate(), "message", SentryLogLevel.WARN), + fixture.scopes.scope, + ) + + sut.captureEvent( + SentryEvent().apply { + exceptions = + listOf(SentryException().apply { mechanism = Mechanism().apply { isHandled = false } }) + } + ) + verify(batchProcessor).flush(eq(500)) + } + @Test fun `cleans up replay folder for Backfillable replay events`() { val dir = File(tmpDir.newFolder().absolutePath)