Skip to content

Commit fcfa576

Browse files
authored
Change continuous profiling to session sample rate (#4180)
* Set continuousProfilesSampleRate and startProfiler() and stopProfiler() as experimental * Added chunk start timestamp to ProfileChunk * Moved setContinuousProfilesSampleRate into ExperimentalOptions * increased chunk duration to 1 minute * replaced continuousProfilesSampleRate with profileSessionSampleRate (Default null) * sample rate is now evaluated inside AndroidContinuousProfiler and every time a session finishes
1 parent 87bdd6d commit fcfa576

26 files changed

+283
-187
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
- Add Continuous Profiling Support ([#3710](https://github.com/getsentry/sentry-java/pull/3710))
88

9-
To enable Continuous Profiling use the `Sentry.startProfiler` and `Sentry.stopProfiler` experimental APIs. Sampling rate can be set through `options.continuousProfilesSampleRate` (defaults to 1.0).
9+
To enable Continuous Profiling use the `Sentry.startProfiler` and `Sentry.stopProfiler` experimental APIs. Sampling rate can be set through `options.continuousProfilesSampleRate`, which defaults to null (disabled).
1010
Note: Both `options.profilesSampler` and `options.profilesSampleRate` must **not** be set to enable Continuous Profiling.
1111

1212
```java
@@ -15,7 +15,7 @@
1515
SentryAndroid.init(context) { options ->
1616

1717
// Currently under experimental options:
18-
options.getExperimental().setContinuousProfilesSampleRate(1.0);
18+
options.getExperimental().setProfileSessionSampleRate(1.0);
1919
}
2020
// Start profiling
2121
Sentry.startProfiler();
@@ -29,7 +29,7 @@
2929
SentryAndroid.init(context) { options ->
3030

3131
// Currently under experimental options:
32-
options.experimental.continuousProfilesSampleRate = 1.0
32+
options.experimental.profileSessionSampleRate = 1.0
3333
}
3434
// Start profiling
3535
Sentry.startProfiler()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public class io/sentry/android/core/AndroidContinuousProfiler : io/sentry/IConti
4242
public fun getProfilerId ()Lio/sentry/protocol/SentryId;
4343
public fun isRunning ()Z
4444
public fun onRateLimitChanged (Lio/sentry/transport/RateLimiter;)V
45-
public fun start ()V
45+
public fun reevaluateSampling ()V
46+
public fun start (Lio/sentry/TracesSampler;)V
4647
public fun stop ()V
4748
}
4849

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.sentry.SentryLevel;
2121
import io.sentry.SentryNanotimeDate;
2222
import io.sentry.SentryOptions;
23+
import io.sentry.TracesSampler;
2324
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
2425
import io.sentry.protocol.SentryId;
2526
import io.sentry.transport.RateLimiter;
@@ -55,6 +56,8 @@ public class AndroidContinuousProfiler
5556
private @NotNull SentryId chunkId = SentryId.EMPTY_ID;
5657
private final @NotNull AtomicBoolean isClosed = new AtomicBoolean(false);
5758
private @NotNull SentryDate startProfileChunkTimestamp = new SentryNanotimeDate();
59+
private boolean shouldSample = true;
60+
private boolean isSampled = false;
5861

5962
public AndroidContinuousProfiler(
6063
final @NotNull BuildInfoProvider buildInfoProvider,
@@ -100,7 +103,24 @@ private void init() {
100103
logger);
101104
}
102105

103-
public synchronized void start() {
106+
public synchronized void start(final @NotNull TracesSampler tracesSampler) {
107+
if (shouldSample) {
108+
isSampled = tracesSampler.sampleSessionProfile();
109+
shouldSample = false;
110+
}
111+
if (!isSampled) {
112+
logger.log(SentryLevel.DEBUG, "Profiler was not started due to sampling decision.");
113+
return;
114+
}
115+
if (isRunning()) {
116+
logger.log(SentryLevel.DEBUG, "Profiler is already running.");
117+
return;
118+
}
119+
logger.log(SentryLevel.DEBUG, "Started Profiler.");
120+
startProfile();
121+
}
122+
123+
private synchronized void startProfile() {
104124
if ((scopes == null || scopes == NoOpScopes.getInstance())
105125
&& Sentry.getCurrentScopes() != NoOpScopes.getInstance()) {
106126
this.scopes = Sentry.getCurrentScopes();
@@ -236,14 +256,18 @@ private synchronized void stop(final boolean restartProfiler) {
236256

237257
if (restartProfiler) {
238258
logger.log(SentryLevel.DEBUG, "Profile chunk finished. Starting a new one.");
239-
start();
259+
startProfile();
240260
} else {
241261
// When the profiler is stopped manually, we have to reset its id
242262
profilerId = SentryId.EMPTY_ID;
243263
logger.log(SentryLevel.DEBUG, "Profile chunk finished.");
244264
}
245265
}
246266

267+
public synchronized void reevaluateSampling() {
268+
shouldSample = true;
269+
}
270+
247271
public synchronized void close() {
248272
stop();
249273
isClosed.set(true);

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ final class ManifestMetadataReader {
6464

6565
static final String PROFILES_SAMPLE_RATE = "io.sentry.traces.profiling.sample-rate";
6666

67-
static final String CONTINUOUS_PROFILES_SAMPLE_RATE =
68-
"io.sentry.traces.profiling.continuous-sample-rate";
67+
static final String PROFILE_SESSION_SAMPLE_RATE =
68+
"io.sentry.traces.profiling.session-sample-rate";
6969

7070
@ApiStatus.Experimental static final String TRACE_SAMPLING = "io.sentry.traces.trace-sampling";
7171
static final String TRACE_PROPAGATION_TARGETS = "io.sentry.traces.trace-propagation-targets";
@@ -318,11 +318,11 @@ static void applyMetadata(
318318
}
319319
}
320320

321-
if (options.getContinuousProfilesSampleRate() == 1.0) {
322-
final double continuousProfilesSampleRate =
323-
readDouble(metadata, logger, CONTINUOUS_PROFILES_SAMPLE_RATE);
324-
if (continuousProfilesSampleRate != -1) {
325-
options.getExperimental().setContinuousProfilesSampleRate(continuousProfilesSampleRate);
321+
if (options.getProfileSessionSampleRate() == null) {
322+
final double profileSessionSampleRate =
323+
readDouble(metadata, logger, PROFILE_SESSION_SAMPLE_RATE);
324+
if (profileSessionSampleRate != -1) {
325+
options.getExperimental().setProfileSessionSampleRate(profileSessionSampleRate);
326326
}
327327
}
328328

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.sentry.SentryExecutorService;
2323
import io.sentry.SentryLevel;
2424
import io.sentry.SentryOptions;
25+
import io.sentry.TracesSampler;
2526
import io.sentry.TracesSamplingDecision;
2627
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
2728
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
@@ -180,7 +181,12 @@ private void createAndStartContinuousProfiler(
180181
appStartMetrics.setAppStartProfiler(null);
181182
appStartMetrics.setAppStartContinuousProfiler(appStartContinuousProfiler);
182183
logger.log(SentryLevel.DEBUG, "App start continuous profiling started.");
183-
appStartContinuousProfiler.start();
184+
SentryOptions sentryOptions = SentryOptions.empty();
185+
// Let's fake a sampler to accept the sampling decision that was calculated on last run
186+
sentryOptions
187+
.getExperimental()
188+
.setProfileSessionSampleRate(profilingOptions.isContinuousProfileSampled() ? 1.0 : 0.0);
189+
appStartContinuousProfiler.start(new TracesSampler(sentryOptions));
184190
}
185191

186192
private void createAndStartTransactionProfiler(

0 commit comments

Comments
 (0)