Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report process init time for app start #3159

Merged
merged 9 commits into from
Feb 12, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Decouple Profiler from Transaction ([#3101](https://github.com/getsentry/sentry-java/pull/3101))
- Add options and sampling logic ([#3121](https://github.com/getsentry/sentry-java/pull/3121))
- Add ContentProvider and start profile ([#3128](https://github.com/getsentry/sentry-java/pull/3128))
- Report process init time as a span for app start performance ([#3159](https://github.com/getsentry/sentry-java/pull/3159))

### Fixes

Expand Down
1 change: 1 addition & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ public class io/sentry/android/core/performance/AppStartMetrics {
public fun getAppStartTimeSpanWithFallback (Lio/sentry/android/core/SentryAndroidOptions;)Lio/sentry/android/core/performance/TimeSpan;
public fun getAppStartType ()Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;
public fun getApplicationOnCreateTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
public fun getClassLoadedUptimeMs ()J
public fun getContentProviderOnCreateTimeSpans ()Ljava/util/List;
public static fun getInstance ()Lio/sentry/android/core/performance/AppStartMetrics;
public fun getSdkInitTimeSpan ()Lio/sentry/android/core/performance/TimeSpan;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ final class PerformanceAndroidEventProcessor implements EventProcessor {
private static final String APP_METRICS_CONTENT_PROVIDER_OP = "contentprovider.load";
private static final String APP_METRICS_ACTIVITIES_OP = "activity.load";
private static final String APP_METRICS_APPLICATION_OP = "application.load";
private static final String APP_METRICS_PROCESS_INIT_OP = "process.load";

private boolean sentStartMeasurement = false;

Expand Down Expand Up @@ -155,6 +156,23 @@ private void attachColdAppStartSpans(
}
}

// Process init
final long classInitUptimeMs = appStartMetrics.getClassLoadedUptimeMs();
final @NotNull TimeSpan appStartTimeSpan = appStartMetrics.getAppStartTimeSpan();
if (appStartTimeSpan.hasStarted()) {
final @NotNull TimeSpan processInitTimeSpan = new TimeSpan();
processInitTimeSpan.setStartedAt(appStartTimeSpan.getStartUptimeMs());
processInitTimeSpan.setStartUnixTimeMs(appStartTimeSpan.getStartTimestampMs());

processInitTimeSpan.setStoppedAt(classInitUptimeMs);
processInitTimeSpan.setDescription("Process Initialization");
markushi marked this conversation as resolved.
Show resolved Hide resolved

txn.getSpans()
.add(
timeSpanToSentrySpan(
processInitTimeSpan, parentSpanId, traceId, APP_METRICS_PROCESS_INIT_OP));
}

// Content Providers
final @NotNull List<TimeSpan> contentProviderOnCreates =
appStartMetrics.getContentProviderOnCreateTimeSpans();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public enum AppStartType {
WARM
}

private static final long CLASS_LOADED_UPTIME_MS = SystemClock.uptimeMillis();

private static volatile @Nullable AppStartMetrics instance;

private @NotNull AppStartType appStartType = AppStartType.UNKNOWN;
Expand Down Expand Up @@ -121,6 +123,10 @@ public void addActivityLifecycleTimeSpans(final @NotNull ActivityLifecycleTimeSp
activityLifecycles.add(timeSpan);
}

public long getClassLoadedUptimeMs() {
return CLASS_LOADED_UPTIME_MS;
}

/**
* @return the app start time span if it was started and perf-2 is enabled, falls back to the sdk
* init time span otherwise
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ class PerformanceAndroidEventProcessorTest {
// then the app start metrics should be attached
tr = sut.process(tr, Hint())

assertTrue(
tr.spans.any {
"process.load" == it.op &&
appStartSpan.spanId == it.parentSpanId
}
)

assertTrue(
tr.spans.any {
"contentprovider.load" == it.op &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.mockito.kotlin.mock
import org.robolectric.annotation.Config
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNull
import kotlin.test.assertSame
import kotlin.test.assertTrue
Expand Down Expand Up @@ -100,4 +101,9 @@ class AppStartMetricsTest {
val sdkInitSpan = AppStartMetrics.getInstance().sdkInitTimeSpan
assertSame(sdkInitSpan, timeSpan)
}

@Test
fun `class load time is set`() {
assertNotEquals(0, AppStartMetrics.getInstance().classLoadedUptimeMs)
}
}
Loading