Skip to content

Commit

Permalink
Add new APIs for Continuous Profiling v8 (p5) (#3844)
Browse files Browse the repository at this point in the history
* AndroidContinuousProfiler now retrieve the scopes on start()
* removed profilesSampleRate from sample app to enable continuous profiling
* added Sentry.startProfiler and Sentry.stopProfiler APIs
  • Loading branch information
stefanosiano authored Nov 14, 2024
1 parent b7e889c commit 540e276
Show file tree
Hide file tree
Showing 21 changed files with 238 additions and 15 deletions.
1 change: 0 additions & 1 deletion sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public class io/sentry/android/core/AndroidContinuousProfiler : io/sentry/IConti
public fun close ()V
public fun getProfilerId ()Lio/sentry/protocol/SentryId;
public fun isRunning ()Z
public fun setScopes (Lio/sentry/IScopes;)V
public fun start ()V
public fun stop ()V
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import io.sentry.ILogger;
import io.sentry.IScopes;
import io.sentry.ISentryExecutorService;
import io.sentry.NoOpScopes;
import io.sentry.PerformanceCollectionData;
import io.sentry.ProfileChunk;
import io.sentry.Sentry;
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
Expand Down Expand Up @@ -88,12 +90,14 @@ private void init() {
logger);
}

public synchronized void setScopes(final @NotNull IScopes scopes) {
this.scopes = scopes;
this.performanceCollector = scopes.getOptions().getCompositePerformanceCollector();
}

public synchronized void start() {
if ((scopes == null || scopes != NoOpScopes.getInstance())
&& Sentry.getCurrentScopes() != NoOpScopes.getInstance()) {
this.scopes = Sentry.getCurrentScopes();
this.performanceCollector =
Sentry.getCurrentScopes().getOptions().getCompositePerformanceCollector();
}

// Debug.startMethodTracingSampling() is only available since Lollipop, but Android Profiler
// causes crashes on api 21 -> https://github.com/getsentry/sentry-java/issues/3392
if (buildInfoProvider.getSdkInfoVersion() < Build.VERSION_CODES.LOLLIPOP_MR1) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.sentry.IScopes
import io.sentry.ISentryExecutorService
import io.sentry.MemoryCollectionData
import io.sentry.PerformanceCollectionData
import io.sentry.Sentry
import io.sentry.SentryLevel
import io.sentry.SentryNanotimeDate
import io.sentry.SentryTracer
Expand Down Expand Up @@ -80,7 +81,7 @@ class AndroidContinuousProfilerTest {
options.profilingTracesDirPath,
options.profilingTracesHz,
options.executorService
).also { it.setScopes(scopes) }
)
}
}

Expand Down Expand Up @@ -118,6 +119,8 @@ class AndroidContinuousProfilerTest {
// Profiler doesn't start if the folder doesn't exists.
// Usually it's generated when calling Sentry.init, but for tests we can create it manually.
File(fixture.options.profilingTracesDirPath!!).mkdirs()

Sentry.setCurrentScopes(fixture.scopes)
}

@AfterTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
<meta-data android:name="io.sentry.traces.sample-rate" android:value="1.0" />

<!-- how to enable profiling when starting transactions -->
<meta-data android:name="io.sentry.traces.profiling.sample-rate" android:value="1" />
<!-- <meta-data android:name="io.sentry.traces.profiling.sample-rate" android:value="1.0" />-->

<!-- how to enable app start profiling -->
<meta-data android:name="io.sentry.traces.profiling.enable-app-start" android:value="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import android.app.Application;
import android.os.StrictMode;
import io.sentry.Sentry;

/** Apps. main Application. */
public class MyApplication extends Application {

@Override
public void onCreate() {
Sentry.startProfiler();
strictMode();
super.onCreate();

Expand Down
18 changes: 16 additions & 2 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,10 @@ public final class io/sentry/HubAdapter : io/sentry/IHub {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -684,8 +686,10 @@ public final class io/sentry/HubScopesWrapper : io/sentry/IHub {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -714,7 +718,6 @@ public abstract interface class io/sentry/IContinuousProfiler {
public abstract fun close ()V
public abstract fun getProfilerId ()Lio/sentry/protocol/SentryId;
public abstract fun isRunning ()Z
public abstract fun setScopes (Lio/sentry/IScopes;)V
public abstract fun start ()V
public abstract fun stop ()V
}
Expand Down Expand Up @@ -921,11 +924,13 @@ public abstract interface class io/sentry/IScopes {
public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public abstract fun setTransaction (Ljava/lang/String;)V
public abstract fun setUser (Lio/sentry/protocol/User;)V
public abstract fun startProfiler ()V
public abstract fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;)Lio/sentry/ITransaction;
public abstract fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun startTransaction (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ITransaction;
public fun startTransaction (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public abstract fun stopProfiler ()V
public abstract fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public abstract fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -1395,7 +1400,6 @@ public final class io/sentry/NoOpContinuousProfiler : io/sentry/IContinuousProfi
public static fun getInstance ()Lio/sentry/NoOpContinuousProfiler;
public fun getProfilerId ()Lio/sentry/protocol/SentryId;
public fun isRunning ()Z
public fun setScopes (Lio/sentry/IScopes;)V
public fun start ()V
public fun stop ()V
}
Expand Down Expand Up @@ -1465,8 +1469,10 @@ public final class io/sentry/NoOpHub : io/sentry/IHub {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -1625,8 +1631,10 @@ public final class io/sentry/NoOpScopes : io/sentry/IScopes {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -2278,8 +2286,10 @@ public final class io/sentry/Scopes : io/sentry/IScopes {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -2343,8 +2353,10 @@ public final class io/sentry/ScopesAdapter : io/sentry/IScopes {
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUser (Lio/sentry/protocol/User;)V
public fun startProfiler ()V
public fun startSession ()V
public fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public fun stopProfiler ()V
public fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down Expand Up @@ -2447,12 +2459,14 @@ public final class io/sentry/Sentry {
public static fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public static fun setTransaction (Ljava/lang/String;)V
public static fun setUser (Lio/sentry/protocol/User;)V
public static fun startProfiler ()V
public static fun startSession ()V
public static fun startTransaction (Lio/sentry/TransactionContext;)Lio/sentry/ITransaction;
public static fun startTransaction (Lio/sentry/TransactionContext;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public static fun startTransaction (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ITransaction;
public static fun startTransaction (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public static fun startTransaction (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TransactionOptions;)Lio/sentry/ITransaction;
public static fun stopProfiler ()V
public static fun withIsolationScope (Lio/sentry/ScopeCallback;)V
public static fun withScope (Lio/sentry/ScopeCallback;)V
}
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/HubAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ public boolean isAncestorOf(final @Nullable IScopes otherScopes) {
return Sentry.startTransaction(transactionContext, transactionOptions);
}

@Override
public void startProfiler() {
Sentry.startProfiler();
}

@Override
public void stopProfiler() {
Sentry.stopProfiler();
}

@Override
public @NotNull SentryId captureProfileChunk(
final @NotNull ProfileChunk profilingContinuousData) {
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/HubScopesWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,16 @@ public boolean isAncestorOf(final @Nullable IScopes otherScopes) {
return scopes.startTransaction(transactionContext, transactionOptions);
}

@Override
public void startProfiler() {
scopes.startProfiler();
}

@Override
public void stopProfiler() {
scopes.stopProfiler();
}

@ApiStatus.Internal
@Override
public void setSpanContext(
Expand Down
2 changes: 0 additions & 2 deletions sentry/src/main/java/io/sentry/IContinuousProfiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ public interface IContinuousProfiler {

void stop();

void setScopes(final @NotNull IScopes scopes);

/** Cancel the profiler and stops it. Used on SDK close. */
void close();

Expand Down
4 changes: 4 additions & 0 deletions sentry/src/main/java/io/sentry/IScopes.java
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,10 @@ ITransaction startTransaction(
final @NotNull TransactionContext transactionContext,
final @NotNull TransactionOptions transactionOptions);

void startProfiler();

void stopProfiler();

/**
* Associates {@link ISpan} and the transaction name with the {@link Throwable}. Used to determine
* in which trace the exception has been thrown in framework integrations.
Expand Down
3 changes: 0 additions & 3 deletions sentry/src/main/java/io/sentry/NoOpContinuousProfiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ public void start() {}
@Override
public void stop() {}

@Override
public void setScopes(@NotNull IScopes scopes) {}

@Override
public boolean isRunning() {
return false;
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ public boolean isAncestorOf(@Nullable IScopes otherScopes) {
return NoOpTransaction.getInstance();
}

@Override
public void startProfiler() {}

@Override
public void stopProfiler() {}

@Override
public void setSpanContext(
final @NotNull Throwable throwable,
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpScopes.java
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ public boolean isAncestorOf(@Nullable IScopes otherScopes) {
return NoOpTransaction.getInstance();
}

@Override
public void startProfiler() {}

@Override
public void stopProfiler() {}

@Override
public void setSpanContext(
final @NotNull Throwable throwable,
Expand Down
28 changes: 28 additions & 0 deletions sentry/src/main/java/io/sentry/Scopes.java
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,34 @@ public void flush(long timeoutMillis) {
return transaction;
}

@Override
public void startProfiler() {
if (getOptions().isContinuousProfilingEnabled()) {
getOptions().getLogger().log(SentryLevel.DEBUG, "Started continuous Profiling.");
getOptions().getContinuousProfiler().start();
} else {
getOptions()
.getLogger()
.log(
SentryLevel.WARNING,
"Continuous Profiling is not enabled. Set profilesSampleRate and profilesSampler to null to enable it.");
}
}

@Override
public void stopProfiler() {
if (getOptions().isContinuousProfilingEnabled()) {
getOptions().getLogger().log(SentryLevel.DEBUG, "Stopped continuous Profiling.");
getOptions().getContinuousProfiler().stop();
} else {
getOptions()
.getLogger()
.log(
SentryLevel.WARNING,
"Continuous Profiling is not enabled. Set profilesSampleRate and profilesSampler to null to enable it.");
}
}

@Override
@ApiStatus.Internal
public void setSpanContext(
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/ScopesAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@ public boolean isAncestorOf(final @Nullable IScopes otherScopes) {
return Sentry.startTransaction(transactionContext, transactionOptions);
}

@Override
public void startProfiler() {
Sentry.startProfiler();
}

@Override
public void stopProfiler() {
Sentry.stopProfiler();
}

@ApiStatus.Internal
@Override
public void setSpanContext(
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/Sentry.java
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,16 @@ public static void endSession() {
return getCurrentScopes().startTransaction(transactionContext, transactionOptions);
}

/** Starts the continuous profiler, if enabled. */
public static void startProfiler() {
getCurrentScopes().startProfiler();
}

/** Starts the continuous profiler, if enabled. */
public static void stopProfiler() {
getCurrentScopes().stopProfiler();
}

/**
* Gets the current active transaction or span.
*
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/test/java/io/sentry/HubAdapterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,14 @@ class HubAdapterTest {
HubAdapter.getInstance().reportFullyDisplayed()
verify(scopes).reportFullyDisplayed()
}

@Test fun `startProfiler calls Hub`() {
HubAdapter.getInstance().startProfiler()
verify(scopes).startProfiler()
}

@Test fun `stopProfiler calls Hub`() {
HubAdapter.getInstance().stopProfiler()
verify(scopes).stopProfiler()
}
}
6 changes: 6 additions & 0 deletions sentry/src/test/java/io/sentry/NoOpHubTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,10 @@ class NoOpHubTest {
sut.withScope(scopeCallback)
verify(scopeCallback).run(NoOpScope.getInstance())
}

@Test
fun `startProfiler doesnt throw`() = sut.startProfiler()

@Test
fun `stopProfiler doesnt throw`() = sut.stopProfiler()
}
10 changes: 10 additions & 0 deletions sentry/src/test/java/io/sentry/ScopesAdapterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,14 @@ class ScopesAdapterTest {
ScopesAdapter.getInstance().reportFullyDisplayed()
verify(scopes).reportFullyDisplayed()
}

@Test fun `startProfiler calls Scopes`() {
ScopesAdapter.getInstance().startProfiler()
verify(scopes).startProfiler()
}

@Test fun `stopProfiler calls Scopes`() {
ScopesAdapter.getInstance().stopProfiler()
verify(scopes).stopProfiler()
}
}
Loading

0 comments on commit 540e276

Please sign in to comment.