Skip to content

Commit 6cd4f31

Browse files
authored
Merge 1141aed into 2a3dd50
2 parents 2a3dd50 + 1141aed commit 6cd4f31

35 files changed

+1609
-538
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Features
6+
7+
- (Internal, Experimental) Attach spans for Application, ContentProvider, and Activities to app-start ([#3057](https://github.com/getsentry/sentry-java/pull/3057))
8+
39
## 7.0.0
410

511
Version 7 of the Sentry Android/Java SDK brings a variety of features and fixes. The most notable changes are:

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

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,6 @@ public final class io/sentry/android/core/AppLifecycleIntegration : io/sentry/In
119119
public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V
120120
}
121121

122-
public final class io/sentry/android/core/AppStartState {
123-
public fun getAppStartEndTime ()Lio/sentry/SentryDate;
124-
public fun getAppStartInterval ()Ljava/lang/Long;
125-
public fun getAppStartMillis ()Ljava/lang/Long;
126-
public fun getAppStartTime ()Lio/sentry/SentryDate;
127-
public static fun getInstance ()Lio/sentry/android/core/AppStartState;
128-
public fun isColdStart ()Ljava/lang/Boolean;
129-
public fun reset ()V
130-
public fun setAppStartMillis (J)V
131-
}
132-
133122
public final class io/sentry/android/core/AppState {
134123
public static fun getInstance ()Lio/sentry/android/core/AppState;
135124
public fun isInBackground ()Ljava/lang/Boolean;
@@ -155,6 +144,7 @@ public final class io/sentry/android/core/BuildInfoProvider {
155144
}
156145

157146
public final class io/sentry/android/core/ContextUtils {
147+
public static fun isForegroundImportance ()Z
158148
}
159149

160150
public class io/sentry/android/core/CurrentActivityHolder {
@@ -276,6 +266,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
276266
public fun isEnableNetworkEventBreadcrumbs ()Z
277267
public fun isEnableRootCheck ()Z
278268
public fun isEnableScopeSync ()Z
269+
public fun isEnableStarfish ()Z
279270
public fun isEnableSystemEventBreadcrumbs ()Z
280271
public fun isReportHistoricalAnrs ()Z
281272
public fun setAnrEnabled (Z)V
@@ -298,6 +289,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
298289
public fun setEnableNetworkEventBreadcrumbs (Z)V
299290
public fun setEnableRootCheck (Z)V
300291
public fun setEnableScopeSync (Z)V
292+
public fun setEnableStarfish (Z)V
301293
public fun setEnableSystemEventBreadcrumbs (Z)V
302294
public fun setNativeSdkName (Ljava/lang/String;)V
303295
public fun setProfilingTracesHz (I)V
@@ -335,17 +327,12 @@ public final class io/sentry/android/core/SentryLogcatAdapter {
335327
public static fun wtf (Ljava/lang/String;Ljava/lang/Throwable;)I
336328
}
337329

338-
public final class io/sentry/android/core/SentryPerformanceProvider : android/app/Application$ActivityLifecycleCallbacks {
330+
public final class io/sentry/android/core/SentryPerformanceProvider {
339331
public fun <init> ()V
340332
public fun attachInfo (Landroid/content/Context;Landroid/content/pm/ProviderInfo;)V
333+
public fun getActivityCallback ()Landroid/app/Application$ActivityLifecycleCallbacks;
341334
public fun getType (Landroid/net/Uri;)Ljava/lang/String;
342-
public fun onActivityCreated (Landroid/app/Activity;Landroid/os/Bundle;)V
343-
public fun onActivityDestroyed (Landroid/app/Activity;)V
344-
public fun onActivityPaused (Landroid/app/Activity;)V
345-
public fun onActivityResumed (Landroid/app/Activity;)V
346-
public fun onActivitySaveInstanceState (Landroid/app/Activity;Landroid/os/Bundle;)V
347-
public fun onActivityStarted (Landroid/app/Activity;)V
348-
public fun onActivityStopped (Landroid/app/Activity;)V
335+
public fun onAppLaunched ()V
349336
public fun onCreate ()Z
350337
}
351338

@@ -397,3 +384,80 @@ public final class io/sentry/android/core/cache/AndroidEnvelopeCache : io/sentry
397384
public fun store (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)V
398385
}
399386

387+
public class io/sentry/android/core/performance/ActivityLifecycleCallbacksAdapter : android/app/Application$ActivityLifecycleCallbacks {
388+
public fun <init> ()V
389+
public fun onActivityCreated (Landroid/app/Activity;Landroid/os/Bundle;)V
390+
public fun onActivityDestroyed (Landroid/app/Activity;)V
391+
public fun onActivityPaused (Landroid/app/Activity;)V
392+
public fun onActivityResumed (Landroid/app/Activity;)V
393+
public fun onActivitySaveInstanceState (Landroid/app/Activity;Landroid/os/Bundle;)V
394+
public fun onActivityStarted (Landroid/app/Activity;)V
395+
public fun onActivityStopped (Landroid/app/Activity;)V
396+
}
397+
398+
public class io/sentry/android/core/performance/ActivityLifecycleTimeSpan : java/lang/Comparable {
399+
public fun <init> ()V
400+
public fun compareTo (Lio/sentry/android/core/performance/ActivityLifecycleTimeSpan;)I
401+
public synthetic fun compareTo (Ljava/lang/Object;)I
402+
public final fun getOnCreate ()Lio/sentry/android/core/performance/TimeSpan;
403+
public final fun getOnStart ()Lio/sentry/android/core/performance/TimeSpan;
404+
}
405+
406+
public class io/sentry/android/core/performance/AppStartMetrics {
407+
public fun <init> ()V
408+
public fun addActivityLifecycleTimeSpans (Lio/sentry/android/core/performance/ActivityLifecycleTimeSpan;)V
409+
public fun clear ()V
410+
public fun getActivityLifecycleTimeSpans ()Ljava/util/List;
411+
public fun getAppStartTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
412+
public fun getAppStartType ()Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
413+
public fun getApplicationOnCreateTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
414+
public fun getContentProviderOnCreateTimeSpans ()Ljava/util/List;
415+
public static fun getInstance ()Lio/sentry/android/core/performance/AppStartMetrics;
416+
public fun getSdkAppStartTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
417+
public fun isAppLaunchedInForeground ()Z
418+
public static fun onApplicationCreate (Landroid/app/Application;)V
419+
public static fun onApplicationPostCreate (Landroid/app/Application;)V
420+
public static fun onContentProviderCreate (Landroid/content/ContentProvider;)V
421+
public static fun onContentProviderPostCreate (Landroid/content/ContentProvider;)V
422+
public fun setAppStartType (Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;)V
423+
}
424+
425+
public final class io/sentry/android/core/performance/AppStartMetrics$AppStartType : java/lang/Enum {
426+
public static final field COLD Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
427+
public static final field UNKNOWN Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
428+
public static final field WARM Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
429+
public static fun valueOf (Ljava/lang/String;)Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
430+
public static fun values ()[Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
431+
}
432+
433+
public class io/sentry/android/core/performance/TimeSpan : java/lang/Comparable {
434+
public fun <init> ()V
435+
public fun compareTo (Lio/sentry/android/core/performance/TimeSpan;)I
436+
public synthetic fun compareTo (Ljava/lang/Object;)I
437+
public fun getDescription ()Ljava/lang/String;
438+
public fun getDurationMs ()J
439+
public fun getProjectedStopTimestamp ()Lio/sentry/SentryDate;
440+
public fun getProjectedStopTimestampMs ()J
441+
public fun getProjectedStopTimestampSecs ()D
442+
public fun getStartTimestamp ()Lio/sentry/SentryDate;
443+
public fun getStartTimestampMs ()J
444+
public fun getStartTimestampSecs ()D
445+
public fun getStartUptimeMs ()J
446+
public fun hasNotStarted ()Z
447+
public fun hasNotStopped ()Z
448+
public fun hasStarted ()Z
449+
public fun hasStopped ()Z
450+
public fun reset ()V
451+
public fun setDescription (Ljava/lang/String;)V
452+
public fun setStartUnixTimeMs (J)V
453+
public fun setStartedAt (J)V
454+
public fun setStoppedAt (J)V
455+
public fun start ()V
456+
public fun stop ()V
457+
}
458+
459+
public class io/sentry/android/core/performance/WindowContentChangedCallback : io/sentry/android/core/internal/gestures/WindowCallbackAdapter {
460+
public fun <init> (Landroid/view/Window$Callback;Ljava/lang/Runnable;)V
461+
public fun onContentChanged ()V
462+
}
463+

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

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import io.sentry.TransactionOptions;
3131
import io.sentry.android.core.internal.util.ClassUtil;
3232
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
33+
import io.sentry.android.core.performance.AppStartMetrics;
34+
import io.sentry.android.core.performance.TimeSpan;
3335
import io.sentry.protocol.MeasurementValue;
3436
import io.sentry.protocol.TransactionNameSource;
3537
import io.sentry.util.Objects;
@@ -70,7 +72,6 @@ public final class ActivityLifecycleIntegration
7072
private boolean isAllActivityCallbacksAvailable;
7173

7274
private boolean firstActivityCreated = false;
73-
private final boolean foregroundImportance;
7475

7576
private @Nullable FullyDisplayedReporter fullyDisplayedReporter = null;
7677
private @Nullable ISpan appStartSpan;
@@ -100,10 +101,6 @@ public ActivityLifecycleIntegration(
100101
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.Q) {
101102
isAllActivityCallbacksAvailable = true;
102103
}
103-
104-
// we only track app start for processes that will show an Activity (full launch).
105-
// Here we check the process importance which will tell us that.
106-
foregroundImportance = ContextUtils.isForegroundImportance();
107104
}
108105

109106
@Override
@@ -182,15 +179,27 @@ private void startTracing(final @NotNull Activity activity) {
182179
if (!performanceEnabled) {
183180
activitiesWithOngoingTransactions.put(activity, NoOpTransaction.getInstance());
184181
TracingUtils.startNewTrace(hub);
185-
} else if (performanceEnabled) {
182+
} else {
186183
// as we allow a single transaction running on the bound Scope, we finish the previous ones
187184
stopPreviousTransactions();
188185

189186
final String activityName = getActivityName(activity);
190187

191-
final SentryDate appStartTime =
192-
foregroundImportance ? AppStartState.getInstance().getAppStartTime() : null;
193-
final Boolean coldStart = AppStartState.getInstance().isColdStart();
188+
final @Nullable SentryDate appStartTime;
189+
final @Nullable Boolean coldStart;
190+
final TimeSpan appStartTimeSpan = getAppStartTimeSpan();
191+
192+
// we only track app start for processes that will show an Activity (full launch).
193+
// Here we check the process importance which will tell us that.
194+
final boolean foregroundImportance = ContextUtils.isForegroundImportance();
195+
if (foregroundImportance && appStartTimeSpan.hasStarted()) {
196+
appStartTime = appStartTimeSpan.getStartTimestamp();
197+
coldStart =
198+
AppStartMetrics.getInstance().getAppStartType() == AppStartMetrics.AppStartType.COLD;
199+
} else {
200+
appStartTime = null;
201+
coldStart = null;
202+
}
194203

195204
final TransactionOptions transactionOptions = new TransactionOptions();
196205
transactionOptions.setDeadlineTimeout(
@@ -407,6 +416,7 @@ public synchronized void onActivityStarted(final @NotNull Activity activity) {
407416
@Override
408417
public synchronized void onActivityResumed(final @NotNull Activity activity) {
409418
if (performanceEnabled) {
419+
410420
final @Nullable ISpan ttidSpan = ttidSpanMap.get(activity);
411421
final @Nullable ISpan ttfdSpan = ttfdSpanMap.get(activity);
412422
final View rootView = activity.findViewById(android.R.id.content);
@@ -536,13 +546,13 @@ private void cancelTtfdAutoClose() {
536546

537547
private void onFirstFrameDrawn(final @Nullable ISpan ttfdSpan, final @Nullable ISpan ttidSpan) {
538548
// app start span
539-
@Nullable final SentryDate appStartStartTime = AppStartState.getInstance().getAppStartTime();
540-
@Nullable final SentryDate appStartEndTime = AppStartState.getInstance().getAppStartEndTime();
549+
final @NotNull TimeSpan appStartTimeSpan = getAppStartTimeSpan();
550+
541551
// in case the SentryPerformanceProvider is disabled it does not set the app start times,
542552
// and we need to set the end time manually here,
543553
// the start time gets set manually in SentryAndroid.init()
544-
if (appStartStartTime != null && appStartEndTime == null) {
545-
AppStartState.getInstance().setAppStartEnd();
554+
if (appStartTimeSpan.hasStarted() && appStartTimeSpan.hasNotStopped()) {
555+
appStartTimeSpan.stop();
546556
}
547557
finishAppStartSpan();
548558

@@ -626,7 +636,15 @@ private void setColdStart(final @Nullable Bundle savedInstanceState) {
626636
if (!firstActivityCreated) {
627637
// if Activity has savedInstanceState then its a warm start
628638
// https://developer.android.com/topic/performance/vitals/launch-time#warm
629-
AppStartState.getInstance().setColdStart(savedInstanceState == null);
639+
// SentryPerformanceProvider sets this already
640+
// pre-starfish: back-fill with best guess
641+
if (options != null && !options.isEnableStarfish()) {
642+
AppStartMetrics.getInstance()
643+
.setAppStartType(
644+
savedInstanceState == null
645+
? AppStartMetrics.AppStartType.COLD
646+
: AppStartMetrics.AppStartType.WARM);
647+
}
630648
}
631649
}
632650

@@ -662,9 +680,18 @@ private void setColdStart(final @Nullable Bundle savedInstanceState) {
662680
}
663681

664682
private void finishAppStartSpan() {
665-
final @Nullable SentryDate appStartEndTime = AppStartState.getInstance().getAppStartEndTime();
683+
final @NotNull TimeSpan appStartTimeSpan = getAppStartTimeSpan();
684+
final @Nullable SentryDate appStartEndTime = appStartTimeSpan.getProjectedStopTimestamp();
666685
if (performanceEnabled && appStartEndTime != null) {
667686
finishSpan(appStartSpan, appStartEndTime);
668687
}
669688
}
689+
690+
private @NotNull TimeSpan getAppStartTimeSpan() {
691+
final @NotNull TimeSpan appStartTimeSpan =
692+
options.isEnableStarfish()
693+
? AppStartMetrics.getInstance().getAppStartTimeSpan()
694+
: AppStartMetrics.getInstance().getSdkAppStartTimeSpan();
695+
return appStartTimeSpan;
696+
}
670697
}

0 commit comments

Comments
 (0)