Skip to content

Commit

Permalink
Do not send session updates for terminated sessions (#2849)
Browse files Browse the repository at this point in the history
  • Loading branch information
romtsn committed Jul 20, 2023
1 parent 0bff5c1 commit 101f707
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Deduplicate events happening in multiple threads simultaneously (e.g. `OutOfMemoryError`) ([#2845](https://github.com/getsentry/sentry-java/pull/2845))
- This will improve Crash-Free Session Rate as we no longer will send multiple Session updates with `Crashed` status, but only the one that is relevant
- Ensure no Java 8 method reference sugar is used for Android ([#2857](https://github.com/getsentry/sentry-java/pull/2857))
- Do not send session updates for terminated sessions ([#2849](https://github.com/getsentry/sentry-java/pull/2849))

## 6.26.0

Expand Down
1 change: 1 addition & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,7 @@ public final class io/sentry/Session : io/sentry/JsonSerializable, io/sentry/Jso
public fun getTimestamp ()Ljava/util/Date;
public fun getUnknown ()Ljava/util/Map;
public fun getUserAgent ()Ljava/lang/String;
public fun isTerminated ()Z
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V
public fun setInitAsTrue ()V
public fun setUnknown (Ljava/util/Map;)V
Expand Down
10 changes: 6 additions & 4 deletions sentry/src/main/java/io/sentry/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ private boolean shouldApplyScopeData(
@Nullable Session session = null;

if (event != null) {
session = updateSessionData(event, hint, scope);
// https://develop.sentry.dev/sdk/sessions/#terminal-session-states
if (sessionBeforeUpdate == null || !sessionBeforeUpdate.isTerminated()) {
session = updateSessionData(event, hint, scope);
}

if (!sample()) {
options
Expand Down Expand Up @@ -490,9 +493,8 @@ Session updateSessionData(
}

if (session.update(status, userAgent, crashedOrErrored, abnormalMechanism)) {
// if we have an uncaughtExceptionHint we can end the session.
if (HintUtils.hasType(
hint, UncaughtExceptionHandlerIntegration.UncaughtExceptionHint.class)) {
// if session terminated we can end it.
if (session.isTerminated()) {
session.end();
}
}
Expand Down
4 changes: 4 additions & 0 deletions sentry/src/main/java/io/sentry/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ public Session(
null);
}

public boolean isTerminated() {
return status != State.Ok;
}

@SuppressWarnings({"JdkObsolete", "JavaUtilDate"})
public @Nullable Date getStarted() {
if (started == null) {
Expand Down
38 changes: 38 additions & 0 deletions sentry/src/test/java/io/sentry/SentryClientTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.sentry

import io.sentry.Scope.IWithPropagationContext
import io.sentry.Session.State.Crashed
import io.sentry.clientreport.ClientReportTestHelper.Companion.assertClientReport
import io.sentry.clientreport.DiscardReason
import io.sentry.clientreport.DiscardedEvent
Expand Down Expand Up @@ -953,6 +954,21 @@ class SentryClientTest {
}
}

@Test
fun `When event is non handled, end the session`() {
val scope = Scope(fixture.sentryOptions)
scope.startSession()

val event = SentryEvent().apply {
exceptions = createNonHandledException()
}
fixture.getSut().updateSessionData(event, Hint(), scope)
scope.withSession {
assertEquals(Session.State.Crashed, it!!.status)
assertNotNull(it.duration)
}
}

@Test
fun `When event is handled, keep level as it is`() {
val scope = Scope(fixture.sentryOptions)
Expand Down Expand Up @@ -1137,6 +1153,28 @@ class SentryClientTest {
}
}

@Test
fun `when session is in terminal state, does not send session update`() {
val sut = fixture.getSut()

val event = SentryEvent().apply {
exceptions = createNonHandledException()
}
val scope = Scope(fixture.sentryOptions)
val sessionPair = scope.startSession()
scope.withSession { it!!.update(Crashed, null, false) }

assertNotNull(sessionPair) {
sut.captureEvent(event, scope, null)
verify(fixture.transport).send(
check {
assertNull(it.items.find { item -> item.header.type == SentryItemType.Session })
},
anyOrNull()
)
}
}

@Test
fun `when contexts property is set on the event, property from scope contexts is not applied`() {
val sut = fixture.getSut()
Expand Down

0 comments on commit 101f707

Please sign in to comment.