Skip to content

Commit 0e7364a

Browse files
markushistefanosianogetsentry-bot
authored
Fix Ensure app start type is set, even when ActivityLifecycleIntegration is not running (#4250)
* Fix Ensure app start type is set, even when ActivityLifecycleIntegration is not running (#4216) * Ensure app start type is set, even when ActivityLifecycleIntegration is not activated * Update Changelog * Add proper tests * Add code comments * Unify handling * Move all app start handling to AppStartMetrics * Make tests happy * Fix flaky RateLimiter test (#4100) * changed RateLimiterTest `close cancels the timer` to use reflection * Update sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java Co-authored-by: Stefano <[email protected]> * Address PR feedback * Fix post-merge conflict * Format code * Address PR feedback * Address PR feedback * Update sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java --------- Co-authored-by: Stefano <[email protected]> Co-authored-by: Sentry Github Bot <[email protected]> * Fix properly reset application/content-provider timespans * Update Changelog * Fix tests --------- Co-authored-by: Stefano <[email protected]> Co-authored-by: Sentry Github Bot <[email protected]>
1 parent 1b7c68d commit 0e7364a

File tree

10 files changed

+324
-332
lines changed

10 files changed

+324
-332
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixes
66

77
- Reduce excessive CPU usage when serializing breadcrumbs to disk for ANRs ([#4181](https://github.com/getsentry/sentry-java/pull/4181))
8+
- Ensure app start type is set, even when ActivityLifecycleIntegration is not running ([#4250](https://github.com/getsentry/sentry-java/pull/4250))
89

910
### Dependencies
1011

sentry-android-core/api/sentry-android-core.api

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,15 +471,15 @@ public class io/sentry/android/core/performance/AppStartMetrics : io/sentry/andr
471471
public static fun getInstance ()Lio/sentry/android/core/performance/AppStartMetrics;
472472
public fun getSdkInitTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
473473
public fun isAppLaunchedInForeground ()Z
474-
public fun isColdStartValid ()Z
475474
public fun onActivityCreated (Landroid/app/Activity;Landroid/os/Bundle;)V
475+
public fun onActivityDestroyed (Landroid/app/Activity;)V
476+
public fun onActivityStarted (Landroid/app/Activity;)V
476477
public fun onAppStartSpansSent ()V
477478
public static fun onApplicationCreate (Landroid/app/Application;)V
478479
public static fun onApplicationPostCreate (Landroid/app/Application;)V
479480
public static fun onContentProviderCreate (Landroid/content/ContentProvider;)V
480481
public static fun onContentProviderPostCreate (Landroid/content/ContentProvider;)V
481-
public fun registerApplicationForegroundCheck (Landroid/app/Application;)V
482-
public fun restartAppStart (J)V
482+
public fun registerLifecycleCallbacks (Landroid/app/Application;)V
483483
public fun setAppLaunchedInForeground (Z)V
484484
public fun setAppStartProfiler (Lio/sentry/ITransactionProfiler;)V
485485
public fun setAppStartSamplingDecision (Lio/sentry/TracesSamplingDecision;)V

sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import android.os.Bundle;
1010
import android.os.Handler;
1111
import android.os.Looper;
12-
import android.os.SystemClock;
1312
import io.sentry.FullyDisplayedReporter;
1413
import io.sentry.IScope;
1514
import io.sentry.IScopes;
@@ -83,7 +82,6 @@ public final class ActivityLifecycleIntegration
8382
private final @NotNull WeakHashMap<Activity, ActivityLifecycleSpanHelper> activitySpanHelpers =
8483
new WeakHashMap<>();
8584
private @NotNull SentryDate lastPausedTime = new SentryNanotimeDate(new Date(0), 0);
86-
private long lastPausedUptimeMillis = 0;
8785
private @Nullable Future<?> ttfdAutoCloseFuture = null;
8886

8987
// WeakHashMap isn't thread safe but ActivityLifecycleCallbacks is only called from the
@@ -400,7 +398,6 @@ public void onActivityPreCreated(
400398
scopes != null
401399
? scopes.getOptions().getDateProvider().now()
402400
: AndroidDateUtils.getCurrentSentryDateTime();
403-
lastPausedUptimeMillis = SystemClock.uptimeMillis();
404401
helper.setOnCreateStartTimestamp(lastPausedTime);
405402
}
406403

@@ -411,7 +408,6 @@ public void onActivityCreated(
411408
onActivityPreCreated(activity, savedInstanceState);
412409
}
413410
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
414-
setColdStart(savedInstanceState);
415411
if (scopes != null && options != null && options.isEnableScreenTracking()) {
416412
final @Nullable String activityClassName = ClassUtil.getClassName(activity);
417413
scopes.configureScope(scope -> scope.setScreen(activityClassName));
@@ -516,7 +512,6 @@ public void onActivityPrePaused(@NotNull Activity activity) {
516512
scopes != null
517513
? scopes.getOptions().getDateProvider().now()
518514
: AndroidDateUtils.getCurrentSentryDateTime();
519-
lastPausedUptimeMillis = SystemClock.uptimeMillis();
520515
}
521516

522517
@Override
@@ -577,7 +572,7 @@ public void onActivityDestroyed(final @NotNull Activity activity) {
577572
// if the activity is opened again and not in memory, transactions will be created normally.
578573
activitiesWithOngoingTransactions.remove(activity);
579574

580-
if (activitiesWithOngoingTransactions.isEmpty()) {
575+
if (activitiesWithOngoingTransactions.isEmpty() && !activity.isChangingConfigurations()) {
581576
clear();
582577
}
583578
}
@@ -586,7 +581,6 @@ public void onActivityDestroyed(final @NotNull Activity activity) {
586581
private void clear() {
587582
firstActivityCreated = false;
588583
lastPausedTime = new SentryNanotimeDate(new Date(0), 0);
589-
lastPausedUptimeMillis = 0;
590584
activitySpanHelpers.clear();
591585
}
592586

@@ -728,27 +722,6 @@ WeakHashMap<Activity, ISpan> getTtfdSpanMap() {
728722
return ttfdSpanMap;
729723
}
730724

731-
private void setColdStart(final @Nullable Bundle savedInstanceState) {
732-
if (!firstActivityCreated) {
733-
final @NotNull TimeSpan appStartSpan = AppStartMetrics.getInstance().getAppStartTimeSpan();
734-
// If the app start span already started and stopped, it means the app restarted without
735-
// killing the process, so we are in a warm start
736-
// If the app has an invalid cold start, it means it was started in the background, like
737-
// via BroadcastReceiver, so we consider it a warm start
738-
if ((appStartSpan.hasStarted() && appStartSpan.hasStopped())
739-
|| (!AppStartMetrics.getInstance().isColdStartValid())) {
740-
AppStartMetrics.getInstance().restartAppStart(lastPausedUptimeMillis);
741-
AppStartMetrics.getInstance().setAppStartType(AppStartMetrics.AppStartType.WARM);
742-
} else {
743-
AppStartMetrics.getInstance()
744-
.setAppStartType(
745-
savedInstanceState == null
746-
? AppStartMetrics.AppStartType.COLD
747-
: AppStartMetrics.AppStartType.WARM);
748-
}
749-
}
750-
}
751-
752725
private @NotNull String getTtidDesc(final @NotNull String activityName) {
753726
return activityName + " initial display";
754727
}

sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public static void init(
156156
}
157157
}
158158
if (context.getApplicationContext() instanceof Application) {
159-
appStartMetrics.registerApplicationForegroundCheck(
159+
appStartMetrics.registerLifecycleCallbacks(
160160
(Application) context.getApplicationContext());
161161
}
162162
final @NotNull TimeSpan sdkInitTimeSpan = appStartMetrics.getSdkInitTimeSpan();

sentry-android-core/src/main/java/io/sentry/android/core/SentryPerformanceProvider.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ private void onAppLaunched(
174174

175175
// performance v2: Uses Process.getStartUptimeMillis()
176176
// requires API level 24+
177-
if (buildInfoProvider.getSdkInfoVersion() < android.os.Build.VERSION_CODES.N) {
178-
return;
177+
if (buildInfoProvider.getSdkInfoVersion() >= android.os.Build.VERSION_CODES.N) {
178+
final @NotNull TimeSpan appStartTimespan = appStartMetrics.getAppStartTimeSpan();
179+
appStartTimespan.setStartedAt(Process.getStartUptimeMillis());
179180
}
180181

181182
if (context instanceof Application) {
@@ -185,8 +186,6 @@ private void onAppLaunched(
185186
return;
186187
}
187188

188-
final @NotNull TimeSpan appStartTimespan = appStartMetrics.getAppStartTimeSpan();
189-
appStartTimespan.setStartedAt(Process.getStartUptimeMillis());
190-
appStartMetrics.registerApplicationForegroundCheck(app);
189+
appStartMetrics.registerLifecycleCallbacks(app);
191190
}
192191
}

0 commit comments

Comments
 (0)