Skip to content

Commit

Permalink
Move all app start handling to AppStartMetrics
Browse files Browse the repository at this point in the history
  • Loading branch information
markushi committed Mar 3, 2025
1 parent 8823143 commit 7c4b39a
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 273 deletions.
6 changes: 3 additions & 3 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -447,22 +447,22 @@ public class io/sentry/android/core/performance/AppStartMetrics : io/sentry/andr
public static fun getInstance ()Lio/sentry/android/core/performance/AppStartMetrics;
public fun getSdkInitTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
public fun isAppLaunchedInForeground ()Z
public fun isColdStartValid ()Z
public fun onActivityCreated (Landroid/app/Activity;Landroid/os/Bundle;)V
public fun onActivityDestroyed (Landroid/app/Activity;)V
public fun onActivityStarted (Landroid/app/Activity;)V
public fun onAppStartSpansSent ()V
public static fun onApplicationCreate (Landroid/app/Application;)V
public static fun onApplicationPostCreate (Landroid/app/Application;)V
public static fun onContentProviderCreate (Landroid/content/ContentProvider;)V
public static fun onContentProviderPostCreate (Landroid/content/ContentProvider;)V
public fun registerApplicationForegroundCheck (Landroid/app/Application;)V
public fun registerLifecycleCallbacks (Landroid/app/Application;)V
public fun restartAppStart (J)V
public fun setAppLaunchedInForeground (Z)V
public fun setAppStartProfiler (Lio/sentry/ITransactionProfiler;)V
public fun setAppStartSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setAppStartType (Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;)V
public fun setClassLoadedUptimeMs (J)V
public fun shouldSendStartMeasurements ()Z
public fun updateAppStartType (ZJ)V
}

public final class io/sentry/android/core/performance/AppStartMetrics$AppStartType : java/lang/Enum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,6 @@ public synchronized void onActivityCreated(
if (!isAllActivityCallbacksAvailable) {
onActivityPreCreated(activity, savedInstanceState);
}
setColdStart(savedInstanceState != null);
if (hub != null && options != null && options.isEnableScreenTracking()) {
final @Nullable String activityClassName = ClassUtil.getClassName(activity);
hub.configureScope(scope -> scope.setScreen(activityClassName));
Expand Down Expand Up @@ -553,17 +552,6 @@ public synchronized void onActivityDestroyed(final @NotNull Activity activity) {
// activity stack still.
// if the activity is opened again and not in memory, transactions will be created normally.
activitiesWithOngoingTransactions.remove(activity);

if (activitiesWithOngoingTransactions.isEmpty()) {
clear();
}
}

private void clear() {
firstActivityCreated = false;
lastPausedTime = new SentryNanotimeDate(new Date(0), 0);
lastPausedUptimeMillis = 0;
activityLifecycleMap.clear();
}

private void finishSpan(final @Nullable ISpan span) {
Expand Down Expand Up @@ -705,12 +693,6 @@ WeakHashMap<Activity, ISpan> getTtfdSpanMap() {
return ttfdSpanMap;
}

private void setColdStart(final boolean hasBundle) {
if (!firstActivityCreated) {
AppStartMetrics.getInstance().updateAppStartType(hasBundle, lastPausedUptimeMillis);
}
}

private @NotNull String getTtidDesc(final @NotNull String activityName) {
return activityName + " initial display";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public static synchronized void init(
}
}
if (context.getApplicationContext() instanceof Application) {
appStartMetrics.registerApplicationForegroundCheck(
appStartMetrics.registerLifecycleCallbacks(
(Application) context.getApplicationContext());
}
final @NotNull TimeSpan sdkInitTimeSpan = appStartMetrics.getSdkInitTimeSpan();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,13 @@
import static io.sentry.Sentry.APP_START_PROFILING_CONFIG_FILE_NAME;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.NonNull;
import io.sentry.ILogger;
import io.sentry.ITransactionProfiler;
import io.sentry.JsonSerializer;
Expand All @@ -24,9 +18,7 @@
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.TracesSamplingDecision;
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
import io.sentry.android.core.performance.ActivityLifecycleCallbacksAdapter;
import io.sentry.android.core.performance.AppStartMetrics;
import io.sentry.android.core.performance.TimeSpan;
import java.io.BufferedReader;
Expand All @@ -35,8 +27,6 @@
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -54,8 +44,6 @@ public final class SentryPerformanceProvider extends EmptySecureContentProvider

private final @NotNull ILogger logger;
private final @NotNull BuildInfoProvider buildInfoProvider;
private final AtomicInteger activeActivitiesCounter = new AtomicInteger();
private final AtomicBoolean firstDrawDone = new AtomicBoolean(false);

@TestOnly
SentryPerformanceProvider(
Expand Down Expand Up @@ -190,8 +178,9 @@ private void onAppLaunched(

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

if (context instanceof Application) {
Expand All @@ -201,61 +190,6 @@ private void onAppLaunched(
return;
}

final @NotNull TimeSpan appStartTimespan = appStartMetrics.getAppStartTimeSpan();
appStartTimespan.setStartedAt(Process.getStartUptimeMillis());
appStartMetrics.registerApplicationForegroundCheck(app);

activityCallback =
new ActivityLifecycleCallbacksAdapter() {

@Override
public void onActivityCreated(
@NotNull Activity activity, @Nullable Bundle savedInstanceState) {
Log.d("TAG", "onActivityCreated");
activeActivitiesCounter.incrementAndGet();

// In case the SDK gets initialized async or the
// ActivityLifecycleIntegration is not enabled (e.g on RN due to Context not being
// instanceof Application)
// the app start type never gets set
if (!firstDrawDone.get()) {
final long now = SystemClock.uptimeMillis();
AppStartMetrics.getInstance().updateAppStartType(savedInstanceState != null, now);
}
}

@Override
public void onActivityStarted(@NotNull Activity activity) {
if (firstDrawDone.get()) {
return;
}
if (activity.getWindow() != null) {
FirstDrawDoneListener.registerForNextDraw(
activity, () -> onAppStartDone(), buildInfoProvider);
} else {
new Handler(Looper.getMainLooper()).post(() -> onAppStartDone());
}
}

@Override
public void onActivityDestroyed(@NonNull Activity activity) {
final int remainingActivities = activeActivitiesCounter.decrementAndGet();
// if the app is moving into background, reset firstDrawDone
// as the next Activity is considered like a new app start
if (remainingActivities == 0 && !activity.isChangingConfigurations()) {
firstDrawDone.set(false);
}
}
};

app.registerActivityLifecycleCallbacks(activityCallback);
}

synchronized void onAppStartDone() {
if (!firstDrawDone.getAndSet(true)) {
final @NotNull AppStartMetrics appStartMetrics = AppStartMetrics.getInstance();
appStartMetrics.getSdkInitTimeSpan().stop();
appStartMetrics.getAppStartTimeSpan().stop();
}
appStartMetrics.registerLifecycleCallbacks(app);
}
}
Loading

0 comments on commit 7c4b39a

Please sign in to comment.