Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -4862,6 +4862,7 @@ public class io/sentry/cache/EnvelopeCache : io/sentry/cache/IEnvelopeCache {
public static fun getPreviousSessionFile (Ljava/lang/String;)Ljava/io/File;
public fun iterator ()Ljava/util/Iterator;
public fun movePreviousSession (Ljava/io/File;Ljava/io/File;)V
public fun persistCurrentSession (Lio/sentry/Session;)V
public fun store (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)V
public fun storeEnvelope (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)Z
public fun waitPreviousSessionFlush ()Z
Expand Down
81 changes: 71 additions & 10 deletions sentry/src/main/java/io/sentry/cache/EnvelopeCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public boolean storeEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
return storeInternal(envelope, hint);
}

@SuppressWarnings("JavaUtilDate")
private boolean storeInternal(final @NotNull SentryEnvelope envelope, final @NotNull Hint hint) {
Objects.requireNonNull(envelope, "Envelope is required.");

Expand All @@ -118,8 +119,22 @@ private boolean storeInternal(final @NotNull SentryEnvelope envelope, final @Not
final File previousSessionFile = getPreviousSessionFile(directoryPath);

if (HintUtils.hasType(hint, SessionEnd.class)) {
if (!currentSessionFile.delete()) {
options.getLogger().log(WARNING, "Current envelope doesn't exist.");
try (final @NotNull ISentryLifecycleToken ignored = sessionLock.acquire()) {
final @Nullable Session endingSession = readSessionFromEnvelope(envelope);
final @Nullable Session currentSession = readSessionFromDisk(currentSessionFile);
final boolean preserveCurrentSession =
endingSession != null
&& currentSession != null
&& currentSession.hasNonTerminatingUnhandledError()
&& endingSession.getSessionId() != null
&& currentSession.getSessionId() != null
&& !Objects.equals(endingSession.getSessionId(), currentSession.getSessionId())
&& endingSession.getStarted() != null
&& currentSession.getStarted() != null
&& currentSession.getStarted().after(endingSession.getStarted());
if (!preserveCurrentSession && !currentSessionFile.delete()) {
options.getLogger().log(WARNING, "Current envelope doesn't exist.");
}
}
}

Expand All @@ -129,8 +144,22 @@ private boolean storeInternal(final @NotNull SentryEnvelope envelope, final @Not
}

if (HintUtils.hasType(hint, SessionStart.class)) {
movePreviousSession(currentSessionFile, previousSessionFile);
updateCurrentSession(currentSessionFile, envelope);
try (final @NotNull ISentryLifecycleToken ignored = sessionLock.acquire()) {
final @Nullable Session startingSession = readSessionFromEnvelope(envelope);
if (startingSession != null) {
final @Nullable Session currentSession = readSessionFromDisk(currentSessionFile);
if (currentSession != null && hasSameSessionId(currentSession, startingSession)) {
if (!isNewerUnhandledOrErrorSnapshot(currentSession, startingSession)) {
writeSessionToDisk(currentSessionFile, startingSession);
}
} else {
movePreviousSession(currentSessionFile, previousSessionFile);
writeSessionToDisk(currentSessionFile, startingSession);
}
} else {
movePreviousSession(currentSessionFile, previousSessionFile);
}
}

boolean crashedLastRun = false;
final File crashMarkerFile = new File(options.getCacheDirPath(), NATIVE_CRASH_MARKER_FILE);
Expand Down Expand Up @@ -274,8 +303,7 @@ private void writeCrashMarkerFile() {
}
}

private void updateCurrentSession(
final @NotNull File currentSessionFile, final @NotNull SentryEnvelope envelope) {
private @Nullable Session readSessionFromEnvelope(final @NotNull SentryEnvelope envelope) {
final Iterable<SentryEnvelopeItem> items = envelope.getItems();

// we know that an envelope with a SessionStart hint has a single item inside
Expand All @@ -295,7 +323,7 @@ private void updateCurrentSession(
"Item of type %s returned null by the parser.",
item.getHeader().getType());
} else {
writeSessionToDisk(currentSessionFile, session);
return session;
}
} catch (Throwable e) {
options.getLogger().log(ERROR, "Item failed to process.", e);
Expand All @@ -309,10 +337,36 @@ private void updateCurrentSession(
item.getHeader().getType());
}
} else {
options
.getLogger()
.log(INFO, "Current envelope %s is empty", currentSessionFile.getAbsolutePath());
options.getLogger().log(INFO, "Current envelope is empty.");
}
return null;
}

private @Nullable Session readSessionFromDisk(final @NotNull File sessionFile) {
if (!sessionFile.exists()) {
return null;
}
try (final Reader reader =
new BufferedReader(new InputStreamReader(new FileInputStream(sessionFile), UTF_8))) {
return serializer.getValue().deserialize(reader, Session.class);
} catch (Exception e) {
options.getLogger().log(ERROR, "Failed to read session from disk.", e);
return null;
}
}

private boolean isNewerUnhandledOrErrorSnapshot(
final @NotNull Session currentSession, final @NotNull Session startingSession) {
return (currentSession.hasNonTerminatingUnhandledError()
&& !startingSession.hasNonTerminatingUnhandledError())
|| currentSession.errorCount() > startingSession.errorCount();
}

private boolean hasSameSessionId(
final @NotNull Session firstSession, final @NotNull Session secondSession) {
return firstSession.getSessionId() != null
&& secondSession.getSessionId() != null
&& Objects.equals(firstSession.getSessionId(), secondSession.getSessionId());
}

private boolean writeEnvelopeToDisk(
Expand Down Expand Up @@ -352,6 +406,13 @@ private void writeSessionToDisk(final @NotNull File file, final @NotNull Session
}
}

@ApiStatus.Internal
public void persistCurrentSession(final @NotNull Session session) {
try (final @NotNull ISentryLifecycleToken ignored = sessionLock.acquire()) {
writeSessionToDisk(getCurrentSessionFile(directory.getOrCreate().getAbsolutePath()), session);
}
}

@Override
public void discard(final @NotNull SentryEnvelope envelope) {
Objects.requireNonNull(envelope, "Envelope is required.");
Expand Down
Loading
Loading