-
-
Notifications
You must be signed in to change notification settings - Fork 427
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
297 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
sentry-android-core/src/main/java/io/sentry/android/core/SendCachedEnvelopeIntegration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package io.sentry.android.core; | ||
|
||
import io.sentry.IHub; | ||
import io.sentry.Integration; | ||
import io.sentry.SendCachedEnvelopeFireAndForgetIntegration; | ||
import io.sentry.SentryLevel; | ||
import io.sentry.SentryOptions; | ||
import io.sentry.util.Objects; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.TimeoutException; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
final class SendCachedEnvelopeIntegration implements Integration { | ||
|
||
private final @NotNull SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForgetFactory | ||
factory; | ||
private final boolean hasStartupCrashMarker; | ||
|
||
public SendCachedEnvelopeIntegration( | ||
final @NotNull SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForgetFactory factory, | ||
final boolean hasStartupCrashMarker) { | ||
this.factory = Objects.requireNonNull(factory, "SendFireAndForgetFactory is required"); | ||
this.hasStartupCrashMarker = hasStartupCrashMarker; | ||
} | ||
|
||
@Override | ||
public void register(@NotNull IHub hub, @NotNull SentryOptions options) { | ||
Objects.requireNonNull(hub, "Hub is required"); | ||
final SentryAndroidOptions androidOptions = | ||
Objects.requireNonNull( | ||
(options instanceof SentryAndroidOptions) ? (SentryAndroidOptions) options : null, | ||
"SentryAndroidOptions is required"); | ||
|
||
final String cachedDir = options.getCacheDirPath(); | ||
if (!factory.hasValidPath(cachedDir, options.getLogger())) { | ||
options.getLogger().log(SentryLevel.ERROR, "No cache dir path is defined in options."); | ||
return; | ||
} | ||
|
||
final SendCachedEnvelopeFireAndForgetIntegration.SendFireAndForget sender = | ||
factory.create(hub, androidOptions); | ||
|
||
if (sender == null) { | ||
androidOptions.getLogger().log(SentryLevel.ERROR, "SendFireAndForget factory is null."); | ||
return; | ||
} | ||
|
||
try { | ||
Future<?> future = | ||
androidOptions | ||
.getExecutorService() | ||
.submit( | ||
() -> { | ||
try { | ||
sender.send(); | ||
} catch (Throwable e) { | ||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.ERROR, "Failed trying to send cached events.", e); | ||
} | ||
}); | ||
|
||
if (hasStartupCrashMarker) { | ||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.DEBUG, "Startup Crash marker exists, blocking flush."); | ||
try { | ||
future.get(androidOptions.getStartupCrashFlushTimeoutMillis(), TimeUnit.MILLISECONDS); | ||
} catch (TimeoutException e) { | ||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.DEBUG, "Synchronous send timed out, continuing in the background."); | ||
} | ||
} else { | ||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.DEBUG, "No Startup Crash marker exists, flushing asynchronously."); | ||
} | ||
|
||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.DEBUG, "SendCachedEnvelopeIntegration installed."); | ||
} catch (Throwable e) { | ||
androidOptions | ||
.getLogger() | ||
.log(SentryLevel.ERROR, "Failed to call the executor. Cached events will not be sent", e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
sentry-android-core/src/main/java/io/sentry/android/core/cache/AndroidEnvelopeCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package io.sentry.android.core.cache; | ||
|
||
import static io.sentry.SentryLevel.DEBUG; | ||
import static io.sentry.SentryLevel.ERROR; | ||
|
||
import android.os.SystemClock; | ||
import io.sentry.Hint; | ||
import io.sentry.SentryEnvelope; | ||
import io.sentry.SentryOptions; | ||
import io.sentry.android.core.AppStartState; | ||
import io.sentry.android.core.SentryAndroidOptions; | ||
import io.sentry.cache.EnvelopeCache; | ||
import io.sentry.hints.DiskFlushNotification; | ||
import io.sentry.util.HintUtils; | ||
import io.sentry.util.Objects; | ||
import java.io.File; | ||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
@ApiStatus.Internal | ||
public final class AndroidEnvelopeCache extends EnvelopeCache { | ||
|
||
public AndroidEnvelopeCache(final @NotNull SentryAndroidOptions options) { | ||
super( | ||
options, | ||
Objects.requireNonNull(options.getCacheDirPath(), "cacheDirPath must not be null"), | ||
options.getMaxCacheItems()); | ||
} | ||
|
||
@Override | ||
public void store(@NotNull SentryEnvelope envelope, @NotNull Hint hint) { | ||
super.store(envelope, hint); | ||
|
||
final SentryAndroidOptions options = (SentryAndroidOptions) this.options; | ||
|
||
final Long appStartTime = AppStartState.getInstance().getAppStartMillis(); | ||
if (HintUtils.hasType(hint, DiskFlushNotification.class) && appStartTime != null) { | ||
long timeSinceSdkInit = SystemClock.uptimeMillis() - appStartTime; | ||
if (timeSinceSdkInit <= options.getStartupCrashDurationThresholdMillis()) { | ||
options | ||
.getLogger() | ||
.log( | ||
DEBUG, | ||
"Startup Crash detected %d milliseconds after SDK init. Writing a startup crash marker file to disk.", | ||
timeSinceSdkInit); | ||
writeStartupCrashMarkerFile(); | ||
} | ||
} | ||
} | ||
|
||
private void writeStartupCrashMarkerFile() { | ||
// we use outbox path always, as it's the one that will also contain markers if hybrid sdks | ||
// decide to write it, which will trigger the blocking init | ||
final String outboxPath = options.getOutboxPath(); | ||
if (outboxPath == null) { | ||
options.getLogger().log(DEBUG, "Outbox path is null, the startup crash marker file will not be written"); | ||
return; | ||
} | ||
final File crashMarkerFile = new File(options.getOutboxPath(), STARTUP_CRASH_MARKER_FILE); | ||
try { | ||
crashMarkerFile.createNewFile(); | ||
} catch (Throwable e) { | ||
options.getLogger().log(ERROR, "Error writing the startup crash marker file to the disk", e); | ||
} | ||
} | ||
|
||
public static boolean hasStartupCrashMarker( | ||
final @NotNull SentryOptions options) { final String outboxPath = options.getOutboxPath(); | ||
if (outboxPath == null) { | ||
options.getLogger().log(DEBUG, "Outbox path is null, the startup crash marker file does not exist"); | ||
return false; | ||
} | ||
|
||
final File crashMarkerFile = new File(options.getOutboxPath(), STARTUP_CRASH_MARKER_FILE); | ||
try { | ||
final boolean exists = crashMarkerFile.exists(); | ||
if (exists) { | ||
if (!crashMarkerFile.delete()) { | ||
options | ||
.getLogger() | ||
.log( | ||
ERROR, | ||
"Failed to delete the startup crash marker file. %s.", | ||
crashMarkerFile.getAbsolutePath()); | ||
} | ||
} | ||
return exists; | ||
} catch (Throwable e) { | ||
options | ||
.getLogger() | ||
.log(ERROR, "Error reading/deleting the startup crash marker file on the disk", e); | ||
} | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.