Skip to content

Commit

Permalink
Merge 44cc99a into a44b5e3
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanosiano authored Jan 8, 2024
2 parents a44b5e3 + 44cc99a commit 42c03a5
Show file tree
Hide file tree
Showing 33 changed files with 955 additions and 98 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Handle `monitor`/`check_in` in client reports and rate limiter ([#3096](https://github.com/getsentry/sentry-java/pull/3096))
- Startup profiling 1 - Decouple Profiler from Transaction ([#3101](https://github.com/getsentry/sentry-java/pull/3101))
- Startup profiling 2 - Add options and sampling logic ([#3121](https://github.com/getsentry/sentry-java/pull/3121))
- Startup Profiling 3 - Add ContentProvider and start profile ([#3128](https://github.com/getsentry/sentry-java/pull/3128))

### Fixes

Expand Down
14 changes: 12 additions & 2 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun getBeforeViewHierarchyCaptureCallback ()Lio/sentry/android/core/SentryAndroidOptions$BeforeCaptureCallback;
public fun getDebugImagesLoader ()Lio/sentry/android/core/IDebugImagesLoader;
public fun getNativeSdkName ()Ljava/lang/String;
public fun getProfilingTracesHz ()I
public fun getProfilingTracesIntervalMillis ()I
public fun getStartupCrashDurationThresholdMillis ()J
public fun isAnrEnabled ()Z
Expand Down Expand Up @@ -305,7 +304,6 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun setEnableScopeSync (Z)V
public fun setEnableSystemEventBreadcrumbs (Z)V
public fun setNativeSdkName (Ljava/lang/String;)V
public fun setProfilingTracesHz (I)V
public fun setProfilingTracesIntervalMillis (I)V
public fun setReportHistoricalAnrs (Z)V
}
Expand Down Expand Up @@ -347,6 +345,14 @@ public final class io/sentry/android/core/SentryPerformanceProvider {
public fun onCreate ()Z
}

public final class io/sentry/android/core/SentryStartupProfilingProvider {
public fun <init> ()V
public fun attachInfo (Landroid/content/Context;Landroid/content/pm/ProviderInfo;)V
public fun getType (Landroid/net/Uri;)Ljava/lang/String;
public fun onCreate ()Z
public fun shutdown ()V
}

public final class io/sentry/android/core/SystemEventsBreadcrumbsIntegration : io/sentry/Integration, java/io/Closeable {
public fun <init> (Landroid/content/Context;)V
public fun <init> (Landroid/content/Context;Ljava/util/List;)V
Expand Down Expand Up @@ -426,12 +432,16 @@ public class io/sentry/android/core/performance/AppStartMetrics {
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;
public fun getStartupProfiler ()Lio/sentry/ITransactionProfiler;
public fun getStartupSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun isAppLaunchedInForeground ()Z
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 setAppStartType (Lio/sentry/android/core/performance/AppStartMetrics$AppStartType;)V
public fun setStartupProfiler (Lio/sentry/ITransactionProfiler;)V
public fun setStartupSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
}

public final class io/sentry/android/core/performance/AppStartMetrics$AppStartType : java/lang/Enum {
Expand Down
6 changes: 6 additions & 0 deletions sentry-android-core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
android:authorities="${applicationId}.SentryInitProvider"
android:exported="false"/>

<provider
android:name=".SentryStartupProfilingProvider"
android:authorities="${applicationId}.SentryStartupProfilingProvider"
android:exported="false"
android:initOrder="201"/>

<provider
android:name=".SentryPerformanceProvider"
android:authorities="${applicationId}.SentryPerformanceProvider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.SpanStatus;
import io.sentry.TracesSamplingDecision;
import io.sentry.TransactionContext;
import io.sentry.TransactionOptions;
import io.sentry.android.core.internal.util.ClassUtil;
Expand Down Expand Up @@ -161,7 +162,7 @@ private void startTracing(final @NotNull Activity activity) {

final @Nullable SentryDate appStartTime;
final @Nullable Boolean coldStart;
final TimeSpan appStartTimeSpan =
final @NotNull TimeSpan appStartTimeSpan =
AppStartMetrics.getInstance().getAppStartTimeSpanWithFallback(options);

// we only track app start for processes that will show an Activity (full launch).
Expand Down Expand Up @@ -205,21 +206,32 @@ private void startTracing(final @NotNull Activity activity) {

// This will be the start timestamp of the transaction, as well as the ttid/ttfd spans
final @NotNull SentryDate ttidStartTime;
final @Nullable TracesSamplingDecision startupSamplingDecision;

if (!(firstActivityCreated || appStartTime == null || coldStart == null)) {
// The first activity ttid/ttfd spans should start at the app start time
ttidStartTime = appStartTime;
// The app start transaction inherits the sampling decision from the startup profiling,
// then clears it
startupSamplingDecision = AppStartMetrics.getInstance().getStartupSamplingDecision();
AppStartMetrics.getInstance().setStartupSamplingDecision(null);
} else {
// The ttid/ttfd spans should start when the previous activity called its onPause method
ttidStartTime = lastPausedTime;
startupSamplingDecision = null;
}
transactionOptions.setStartTimestamp(ttidStartTime);

// we can only bind to the scope if there's no running transaction
ITransaction transaction =
hub.startTransaction(
new TransactionContext(activityName, TransactionNameSource.COMPONENT, UI_LOAD_OP),
transactionOptions);
new TransactionContext(
activityName,
TransactionNameSource.COMPONENT,
UI_LOAD_OP,
startupSamplingDecision),
transactionOptions,
startupSamplingDecision != null);
setSpanOrigin(transaction);

// in case appStartTime isn't available, we don't create a span for it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.sentry.DeduplicateMultithreadedEventProcessor;
import io.sentry.DefaultTransactionPerformanceCollector;
import io.sentry.ILogger;
import io.sentry.ITransactionProfiler;
import io.sentry.NoOpConnectionStatusProvider;
import io.sentry.SendFireAndForgetEnvelopeSender;
import io.sentry.SendFireAndForgetOutboxSender;
Expand All @@ -19,6 +20,7 @@
import io.sentry.android.core.internal.util.AndroidConnectionStatusProvider;
import io.sentry.android.core.internal.util.AndroidMainThreadChecker;
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.timber.SentryTimberIntegration;
import io.sentry.cache.PersistingOptionsObserver;
Expand All @@ -34,6 +36,7 @@
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

/**
Expand Down Expand Up @@ -101,7 +104,7 @@ static void loadDefaultAndMetadataOptions(
options.setFlushTimeoutMillis(DEFAULT_FLUSH_TIMEOUT_MS);

ManifestMetadataReader.applyMetadata(context, options, buildInfoProvider);
initializeCacheDirs(context, options);
options.setCacheDirPath(getCacheDir(context).getAbsolutePath());

readDefaultOptionValues(options, context, buildInfoProvider);
}
Expand Down Expand Up @@ -145,10 +148,23 @@ static void initializeIntegrationsAndProcessors(
options.addEventProcessor(new ViewHierarchyEventProcessor(options));
options.addEventProcessor(new AnrV2EventProcessor(context, options, buildInfoProvider));
options.setTransportGate(new AndroidTransportGate(options));
final SentryFrameMetricsCollector frameMetricsCollector =
new SentryFrameMetricsCollector(context, options, buildInfoProvider);
options.setTransactionProfiler(
new AndroidTransactionProfiler(context, options, buildInfoProvider, frameMetricsCollector));

// Check if the profiler was already instantiated in the startup.
// We use the Android profiler, that uses a global start/stop api, so we need to preserve the
// state of the profiler, and it's only possible retaining the instance.
final @Nullable ITransactionProfiler startupProfiler =
AppStartMetrics.getInstance().getStartupProfiler();
if (startupProfiler != null) {
options.setTransactionProfiler(startupProfiler);
AppStartMetrics.getInstance().setStartupProfiler(null);
} else {
final SentryFrameMetricsCollector frameMetricsCollector =
new SentryFrameMetricsCollector(context, options, buildInfoProvider);
options.setTransactionProfiler(
new AndroidTransactionProfiler(
context, options, buildInfoProvider, frameMetricsCollector));
}

options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger()));
options.setDebugMetaLoader(new AssetsDebugMetaLoader(context, options.getLogger()));

Expand Down Expand Up @@ -319,14 +335,11 @@ private static void readDefaultOptionValues(
}

/**
* Sets the cache dirs like sentry, outbox and sessions
* Retrieve the Sentry cache dir.
*
* @param context the Application context
* @param options the SentryAndroidOptions
*/
private static void initializeCacheDirs(
final @NotNull Context context, final @NotNull SentryAndroidOptions options) {
final File cacheDir = new File(context.getCacheDir(), "sentry");
options.setCacheDirPath(cacheDir.getAbsolutePath());
static @NotNull File getCacheDir(final @NotNull Context context) {
return new File(context.getCacheDir(), "sentry");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ public synchronized void bindTransaction(final @NotNull ITransaction transaction
endData.measurementsMap);
}

@Override
public boolean isRunning() {
return transactionsCounter != 0;
}

@Override
public void close() {
// we stop profiling
Expand All @@ -307,6 +312,10 @@ public void close() {
true,
null,
HubAdapter.getInstance().getOptions());
} else {
// in case the startup profiling is running, and it's not bound to a transaction, we still
// stop profiling, but we also have to manually update the counter.
transactionsCounter--;
}

// we have to first stop profiling otherwise we would lost the last profile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ final class ManifestMetadataReader {

static final String ENABLE_PERFORMANCE_V2 = "io.sentry.performance-v2.enable";

static final String ENABLE_STARTUP_PROFILING = "io.sentry.profiling.enable-startup";

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

Expand Down Expand Up @@ -365,6 +367,10 @@ static void applyMetadata(

options.setEnablePerformanceV2(
readBool(metadata, logger, ENABLE_PERFORMANCE_V2, options.isEnablePerformanceV2()));

options.setEnableStartupProfiling(
readBool(
metadata, logger, ENABLE_STARTUP_PROFILING, options.isEnableStartupProfiling()));
}

options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,6 @@ public final class SentryAndroidOptions extends SentryOptions {
*/
private boolean enableActivityLifecycleTracingAutoFinish = true;

/**
* Profiling traces rate. 101 hz means 101 traces in 1 second. Defaults to 101 to avoid possible
* lockstep sampling. More on
* https://stackoverflow.com/questions/45470758/what-is-lockstep-sampling
*/
private int profilingTracesHz = 101;

/** Interface that loads the debug images list */
private @NotNull IDebugImagesLoader debugImagesLoader = NoOpDebugImagesLoader.getInstance();

Expand Down Expand Up @@ -362,22 +355,6 @@ public int getProfilingTracesIntervalMillis() {
@Deprecated
public void setProfilingTracesIntervalMillis(final int profilingTracesIntervalMillis) {}

/**
* Returns the rate the profiler will sample rates at. 100 hz means 100 traces in 1 second.
*
* @return Rate the profiler will sample rates at.
*/
@ApiStatus.Internal
public int getProfilingTracesHz() {
return profilingTracesHz;
}

/** Sets the rate the profiler will sample rates at. 100 hz means 100 traces in 1 second. */
@ApiStatus.Internal
public void setProfilingTracesHz(final int profilingTracesHz) {
this.profilingTracesHz = profilingTracesHz;
}

/**
* Returns the Debug image loader
*
Expand Down
Loading

0 comments on commit 42c03a5

Please sign in to comment.