Skip to content

Commit

Permalink
Merge 9cafe43 into 1b445e4
Browse files Browse the repository at this point in the history
  • Loading branch information
romtsn authored Apr 9, 2024
2 parents 1b445e4 + 9cafe43 commit 54ce31d
Show file tree
Hide file tree
Showing 152 changed files with 7,050 additions and 386 deletions.
5 changes: 4 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ subprojects {
"sentry-android-ndk",
"sentry-android-okhttp",
"sentry-android-sqlite",
"sentry-android-replay",
"sentry-android-timber"
)
if (jacocoAndroidModules.contains(name)) {
Expand Down Expand Up @@ -305,7 +306,9 @@ private val androidLibs = setOf(
"sentry-android-navigation",
"sentry-android-okhttp",
"sentry-android-timber",
"sentry-compose-android"
"sentry-compose-android",
"sentry-android-sqlite",
"sentry-android-replay"
)

private val androidXLibs = listOf(
Expand Down
2 changes: 2 additions & 0 deletions buildSrc/src/main/java/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ object Config {

val minSdkVersion = 19
val minSdkVersionOkHttp = 21
val minSdkVersionReplay = 19
val minSdkVersionNdk = 19
val minSdkVersionCompose = 21
val targetSdkVersion = sdkVersion
Expand Down Expand Up @@ -194,6 +195,7 @@ object Config {
val jsonUnit = "net.javacrumbs.json-unit:json-unit:2.32.0"
val hsqldb = "org.hsqldb:hsqldb:2.6.1"
val javaFaker = "com.github.javafaker:javafaker:1.0.2"
val msgpack = "org.msgpack:msgpack-core:0.9.8"
}

object QualityPlugins {
Expand Down
2 changes: 2 additions & 0 deletions sentry-android-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ dependencies {
api(projects.sentry)
compileOnly(projects.sentryAndroidFragment)
compileOnly(projects.sentryAndroidTimber)
compileOnly(projects.sentryAndroidReplay)
compileOnly(projects.sentryCompose)

// lifecycle processor, session tracking
Expand Down Expand Up @@ -103,6 +104,7 @@ dependencies {
testImplementation(projects.sentryTestSupport)
testImplementation(projects.sentryAndroidFragment)
testImplementation(projects.sentryAndroidTimber)
testImplementation(projects.sentryAndroidReplay)
testImplementation(projects.sentryComposeHelper)
testImplementation(projects.sentryAndroidNdk)
testRuntimeOnly(Config.Libs.composeUi)
Expand Down
6 changes: 6 additions & 0 deletions sentry-android-core/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@
-keepnames class io.sentry.exception.SentryHttpClientException

##---------------End: proguard configuration for sentry-okhttp ----------

##---------------Begin: proguard configuration for sentry-android-replay ----------
-dontwarn io.sentry.android.replay.ReplayIntegration
-dontwarn io.sentry.android.replay.ReplayIntegrationKt
-keepnames class io.sentry.android.replay.ReplayIntegration
##---------------End: proguard configuration for sentry-android-replay ----------
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
import io.sentry.android.core.performance.AppStartMetrics;
import io.sentry.android.fragment.FragmentLifecycleIntegration;
import io.sentry.android.replay.ReplayIntegration;
import io.sentry.android.timber.SentryTimberIntegration;
import io.sentry.cache.PersistingOptionsObserver;
import io.sentry.cache.PersistingScopeObserver;
import io.sentry.compose.gestures.ComposeGestureTargetLocator;
import io.sentry.compose.viewhierarchy.ComposeViewHierarchyExporter;
import io.sentry.internal.gestures.GestureTargetLocator;
import io.sentry.internal.viewhierarchy.ViewHierarchyExporter;
import io.sentry.transport.CurrentDateProvider;
import io.sentry.transport.NoOpEnvelopeCache;
import io.sentry.util.LazyEvaluator;
import io.sentry.util.Objects;
Expand Down Expand Up @@ -237,7 +239,8 @@ static void installDefaultIntegrations(
final @NotNull LoadClass loadClass,
final @NotNull ActivityFramesTracker activityFramesTracker,
final boolean isFragmentAvailable,
final boolean isTimberAvailable) {
final boolean isTimberAvailable,
final boolean isReplayAvailable) {

// Integration MUST NOT cache option values in ctor, as they will be configured later by the
// user
Expand Down Expand Up @@ -302,6 +305,12 @@ static void installDefaultIntegrations(
new NetworkBreadcrumbsIntegration(context, buildInfoProvider, options.getLogger()));
options.addIntegration(new TempSensorBreadcrumbsIntegration(context));
options.addIntegration(new PhoneStateBreadcrumbsIntegration(context));
if (isReplayAvailable) {
final ReplayIntegration replay =
new ReplayIntegration(context, CurrentDateProvider.getInstance());
options.addIntegration(replay);
options.setReplayController(replay);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.sentry.SentryBaseEvent;
import io.sentry.SentryEvent;
import io.sentry.SentryLevel;
import io.sentry.SentryReplayEvent;
import io.sentry.android.core.internal.util.AndroidMainThreadChecker;
import io.sentry.android.core.performance.AppStartMetrics;
import io.sentry.android.core.performance.TimeSpan;
Expand Down Expand Up @@ -303,4 +304,17 @@ private void setSideLoadedInfo(final @NotNull SentryBaseEvent event) {

return transaction;
}

@Override
public @NotNull SentryReplayEvent process(
final @NotNull SentryReplayEvent event, final @NotNull Hint hint) {
final boolean applyScopeData = shouldApplyScopeData(event, hint);
if (applyScopeData) {
processNonCachedEvent(event, hint);
}

setCommons(event, false, applyScopeData);

return event;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.sentry.transport.ICurrentDateProvider;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -19,11 +20,12 @@
final class LifecycleWatcher implements DefaultLifecycleObserver {

private final AtomicLong lastUpdatedSession = new AtomicLong(0L);
private final AtomicBoolean isFreshSession = new AtomicBoolean(false);

private final long sessionIntervalMillis;

private @Nullable TimerTask timerTask;
private final @Nullable Timer timer;
private final @NotNull Timer timer = new Timer(true);
private final @NotNull Object timerLock = new Object();
private final @NotNull IHub hub;
private final boolean enableSessionTracking;
Expand Down Expand Up @@ -55,11 +57,6 @@ final class LifecycleWatcher implements DefaultLifecycleObserver {
this.enableAppLifecycleBreadcrumbs = enableAppLifecycleBreadcrumbs;
this.hub = hub;
this.currentDateProvider = currentDateProvider;
if (enableSessionTracking) {
timer = new Timer(true);
} else {
timer = null;
}
}

// App goes to foreground
Expand All @@ -74,41 +71,46 @@ public void onStart(final @NotNull LifecycleOwner owner) {
}

private void startSession() {
if (enableSessionTracking) {
cancelTask();
cancelTask();

final long currentTimeMillis = currentDateProvider.getCurrentTimeMillis();
final long currentTimeMillis = currentDateProvider.getCurrentTimeMillis();

hub.configureScope(
scope -> {
if (lastUpdatedSession.get() == 0L) {
final @Nullable Session currentSession = scope.getSession();
if (currentSession != null && currentSession.getStarted() != null) {
lastUpdatedSession.set(currentSession.getStarted().getTime());
}
hub.configureScope(
scope -> {
if (lastUpdatedSession.get() == 0L) {
final @Nullable Session currentSession = scope.getSession();
if (currentSession != null && currentSession.getStarted() != null) {
lastUpdatedSession.set(currentSession.getStarted().getTime());
isFreshSession.set(true);
}
});
}
});

final long lastUpdatedSession = this.lastUpdatedSession.get();
if (lastUpdatedSession == 0L
|| (lastUpdatedSession + sessionIntervalMillis) <= currentTimeMillis) {
final long lastUpdatedSession = this.lastUpdatedSession.get();
if (lastUpdatedSession == 0L
|| (lastUpdatedSession + sessionIntervalMillis) <= currentTimeMillis) {
if (enableSessionTracking) {
addSessionBreadcrumb("start");
hub.startSession();
}
this.lastUpdatedSession.set(currentTimeMillis);
hub.getOptions().getReplayController().start();
} else if (!isFreshSession.get()) {
// only resume if it's not a fresh session, which has been started in SentryAndroid.init
hub.getOptions().getReplayController().resume();
}
isFreshSession.set(false);
this.lastUpdatedSession.set(currentTimeMillis);
}

// App went to background and triggered this callback after 700ms
// as no new screen was shown
@Override
public void onStop(final @NotNull LifecycleOwner owner) {
if (enableSessionTracking) {
final long currentTimeMillis = currentDateProvider.getCurrentTimeMillis();
this.lastUpdatedSession.set(currentTimeMillis);
final long currentTimeMillis = currentDateProvider.getCurrentTimeMillis();
this.lastUpdatedSession.set(currentTimeMillis);

scheduleEndSession();
}
hub.getOptions().getReplayController().pause();
scheduleEndSession();

AppState.getInstance().setInBackground(true);
addAppBreadcrumb("background");
Expand All @@ -122,8 +124,11 @@ private void scheduleEndSession() {
new TimerTask() {
@Override
public void run() {
addSessionBreadcrumb("end");
hub.endSession();
if (enableSessionTracking) {
addSessionBreadcrumb("end");
hub.endSession();
}
hub.getOptions().getReplayController().stop();
}
};

Expand Down Expand Up @@ -164,7 +169,7 @@ TimerTask getTimerTask() {
}

@TestOnly
@Nullable
@NotNull
Timer getTimer() {
return timer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ final class ManifestMetadataReader {

static final String ENABLE_METRICS = "io.sentry.enable-metrics";

static final String REPLAYS_SESSION_SAMPLE_RATE = "io.sentry.session-replay.session-sample-rate";

static final String REPLAYS_ERROR_SAMPLE_RATE = "io.sentry.session-replay.error-sample-rate";

static final String REPLAYS_REDACT_ALL_TEXT = "io.sentry.session-replay.redact-all-text";

static final String REPLAYS_REDACT_ALL_IMAGES = "io.sentry.session-replay.redact-all-images";

/** ManifestMetadataReader ctor */
private ManifestMetadataReader() {}

Expand Down Expand Up @@ -382,6 +390,41 @@ static void applyMetadata(

options.setEnableMetrics(
readBool(metadata, logger, ENABLE_METRICS, options.isEnableMetrics()));

if (options.getExperimental().getSessionReplay().getSessionSampleRate() == null) {
final Double sessionSampleRate =
readDouble(metadata, logger, REPLAYS_SESSION_SAMPLE_RATE);
if (sessionSampleRate != -1) {
options.getExperimental().getSessionReplay().setSessionSampleRate(sessionSampleRate);
}
}

if (options.getExperimental().getSessionReplay().getErrorSampleRate() == null) {
final Double errorSampleRate = readDouble(metadata, logger, REPLAYS_ERROR_SAMPLE_RATE);
if (errorSampleRate != -1) {
options.getExperimental().getSessionReplay().setErrorSampleRate(errorSampleRate);
}
}

options
.getExperimental()
.getSessionReplay()
.setRedactAllText(
readBool(
metadata,
logger,
REPLAYS_REDACT_ALL_TEXT,
options.getExperimental().getSessionReplay().getRedactAllText()));

options
.getExperimental()
.getSessionReplay()
.setRedactAllImages(
readBool(
metadata,
logger,
REPLAYS_REDACT_ALL_IMAGES,
options.getExperimental().getSessionReplay().getRedactAllImages()));
}

options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public final class SentryAndroid {
static final String SENTRY_TIMBER_INTEGRATION_CLASS_NAME =
"io.sentry.android.timber.SentryTimberIntegration";

static final String SENTRY_REPLAY_INTEGRATION_CLASS_NAME =
"io.sentry.android.replay.ReplayIntegration";

private static boolean isReplayAvailable = false;

private static final String TIMBER_CLASS_NAME = "timber.log.Timber";
private static final String FRAGMENT_CLASS_NAME =
"androidx.fragment.app.FragmentManager$FragmentLifecycleCallbacks";
Expand Down Expand Up @@ -99,6 +104,8 @@ public static synchronized void init(
final boolean isTimberAvailable =
(isTimberUpstreamAvailable
&& classLoader.isClassAvailable(SENTRY_TIMBER_INTEGRATION_CLASS_NAME, options));
isReplayAvailable =
classLoader.isClassAvailable(SENTRY_REPLAY_INTEGRATION_CLASS_NAME, options);

final BuildInfoProvider buildInfoProvider = new BuildInfoProvider(logger);
final LoadClass loadClass = new LoadClass();
Expand All @@ -118,7 +125,8 @@ public static synchronized void init(
loadClass,
activityFramesTracker,
isFragmentAvailable,
isTimberAvailable);
isTimberAvailable,
isReplayAvailable);

configuration.configure(options);

Expand All @@ -145,9 +153,12 @@ public static synchronized void init(
true);

final @NotNull IHub hub = Sentry.getCurrentHub();
if (hub.getOptions().isEnableAutoSessionTracking() && ContextUtils.isForegroundImportance()) {
hub.addBreadcrumb(BreadcrumbFactory.forSession("session.start"));
hub.startSession();
if (ContextUtils.isForegroundImportance()) {
if (hub.getOptions().isEnableAutoSessionTracking()) {
hub.addBreadcrumb(BreadcrumbFactory.forSession("session.start"));
hub.startSession();
}
hub.getOptions().getReplayController().start();
}
} catch (IllegalAccessException e) {
logger.log(SentryLevel.FATAL, "Fatal error during SentryAndroid.init(...)", e);
Expand Down
Loading

0 comments on commit 54ce31d

Please sign in to comment.