diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api index 97f7cddb7c0..adcc6ea87d7 100644 --- a/sentry-android-core/api/sentry-android-core.api +++ b/sentry-android-core/api/sentry-android-core.api @@ -204,7 +204,7 @@ public abstract interface class io/sentry/android/core/IDebugImagesLoader { public final class io/sentry/android/core/InternalSentrySdk { public fun ()V - public static fun captureEnvelope ([B)Lio/sentry/protocol/SentryId; + public static fun captureEnvelope ([BZ)Lio/sentry/protocol/SentryId; public static fun getAppStartMeasurement ()Ljava/util/Map; public static fun getCurrentScope ()Lio/sentry/IScope; public static fun serializeScope (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/IScope;)Ljava/util/Map; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java b/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java index a4d1db09df3..7a8fe33a47f 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java @@ -1,5 +1,9 @@ package io.sentry.android.core; +import static io.sentry.SentryLevel.DEBUG; +import static io.sentry.SentryLevel.INFO; +import static io.sentry.SentryLevel.WARNING; + import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -10,6 +14,7 @@ import io.sentry.IScope; import io.sentry.ISerializer; import io.sentry.ObjectWriter; +import io.sentry.Sentry; import io.sentry.SentryEnvelope; import io.sentry.SentryEnvelopeItem; import io.sentry.SentryEvent; @@ -19,12 +24,14 @@ import io.sentry.android.core.performance.ActivityLifecycleTimeSpan; import io.sentry.android.core.performance.AppStartMetrics; import io.sentry.android.core.performance.TimeSpan; +import io.sentry.cache.EnvelopeCache; import io.sentry.protocol.App; import io.sentry.protocol.Device; import io.sentry.protocol.SentryId; import io.sentry.protocol.User; import io.sentry.util.MapObjectWriter; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; @@ -148,7 +155,8 @@ public static Map serializeScope( * captured */ @Nullable - public static SentryId captureEnvelope(final @NotNull byte[] envelopeData) { + public static SentryId captureEnvelope( + final @NotNull byte[] envelopeData, final boolean maybeStartNewSession) { final @NotNull IHub hub = HubAdapter.getInstance(); final @NotNull SentryOptions options = hub.getOptions(); @@ -184,6 +192,10 @@ public static SentryId captureEnvelope(final @NotNull byte[] envelopeData) { if (session != null) { final SentryEnvelopeItem sessionItem = SentryEnvelopeItem.fromSession(serializer, session); envelopeItems.add(sessionItem); + deleteCurrentSessionFile(options); + if (maybeStartNewSession) { + Sentry.startSession(); + } } final SentryEnvelope repackagedEnvelope = @@ -233,7 +245,7 @@ private static void addTimeSpanToSerializedSpans(TimeSpan span, List() + Sentry.configureScope { scope -> + scopeRef.set(scope) + } + + // first envelope is the new session start + val capturedStartSessionEnvelope = fixture.capturedEnvelopes.first() + val capturedNewSessionStart = fixture.options.serializer.deserialize( + InputStreamReader(ByteArrayInputStream(capturedStartSessionEnvelope.items.toList()[0].data)), + Session::class.java + )!! + assertEquals(capturedNewSessionStart.sessionId, scopeRef.get().session!!.sessionId) + assertEquals(Session.State.Ok, capturedNewSessionStart.status) + + val capturedEnvelope = fixture.capturedEnvelopes.last() + val capturedEnvelopeItems = capturedEnvelope.items.toList() + + // there should be two envelopes session start and captured crash + assertEquals(2, fixture.capturedEnvelopes.size) + + // then it should contain the original event + session + assertEquals(2, capturedEnvelopeItems.size) + assertEquals(SentryItemType.Event, capturedEnvelopeItems[0].header.type) + assertEquals(SentryItemType.Session, capturedEnvelopeItems[1].header.type) + + // and then the sent session should be marked as crashed + val capturedSession = fixture.options.serializer.deserialize( + InputStreamReader(ByteArrayInputStream(capturedEnvelopeItems[1].data)), + Session::class.java + )!! + assertEquals(Session.State.Crashed, capturedSession.status) + + // and the local session should be a new session + assertNotEquals(capturedSession.sessionId, scopeRef.get().session!!.sessionId) } @Test diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index d29b04dd7d7..567e9d15110 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -667,6 +667,7 @@ public abstract interface class io/sentry/IScope { public abstract fun clear ()V public abstract fun clearAttachments ()V public abstract fun clearBreadcrumbs ()V + public abstract fun clearSession ()V public abstract fun clearTransaction ()V public abstract fun clone ()Lio/sentry/IScope; public abstract fun endSession ()Lio/sentry/Session; @@ -1221,6 +1222,7 @@ public final class io/sentry/NoOpScope : io/sentry/IScope { public fun clear ()V public fun clearAttachments ()V public fun clearBreadcrumbs ()V + public fun clearSession ()V public fun clearTransaction ()V public fun clone ()Lio/sentry/IScope; public synthetic fun clone ()Ljava/lang/Object; @@ -1592,6 +1594,7 @@ public final class io/sentry/Scope : io/sentry/IScope { public fun clear ()V public fun clearAttachments ()V public fun clearBreadcrumbs ()V + public fun clearSession ()V public fun clearTransaction ()V public fun clone ()Lio/sentry/IScope; public synthetic fun clone ()Ljava/lang/Object; diff --git a/sentry/src/main/java/io/sentry/IScope.java b/sentry/src/main/java/io/sentry/IScope.java index 3842fb2c3a8..3064df8f79a 100644 --- a/sentry/src/main/java/io/sentry/IScope.java +++ b/sentry/src/main/java/io/sentry/IScope.java @@ -352,6 +352,9 @@ public interface IScope { @Nullable Session getSession(); + @ApiStatus.Internal + void clearSession(); + @ApiStatus.Internal void setPropagationContext(final @NotNull PropagationContext propagationContext); diff --git a/sentry/src/main/java/io/sentry/NoOpScope.java b/sentry/src/main/java/io/sentry/NoOpScope.java index c756fb49a39..ed787b00290 100644 --- a/sentry/src/main/java/io/sentry/NoOpScope.java +++ b/sentry/src/main/java/io/sentry/NoOpScope.java @@ -219,6 +219,10 @@ public void withTransaction(Scope.@NotNull IWithTransaction callback) {} return null; } + @ApiStatus.Internal + @Override + public void clearSession() {} + @ApiStatus.Internal @Override public void setPropagationContext(@NotNull PropagationContext propagationContext) {} diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 91c9fcd8cfe..356ee2b57c5 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -913,6 +913,12 @@ public SentryOptions getOptions() { return session; } + @ApiStatus.Internal + @Override + public void clearSession() { + session = null; + } + @ApiStatus.Internal @Override public void setPropagationContext(final @NotNull PropagationContext propagationContext) {