Skip to content

added SentryOptions.continuousProfilesSampleRate #4013

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ final class ManifestMetadataReader {

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

static final String CONTINUOUS_PROFILES_SAMPLE_RATE =
"io.sentry.traces.profiling.continuous-sample-rate";

@ApiStatus.Experimental static final String TRACE_SAMPLING = "io.sentry.traces.trace-sampling";
static final String TRACE_PROPAGATION_TARGETS = "io.sentry.traces.trace-propagation-targets";

Expand Down Expand Up @@ -315,6 +318,14 @@ static void applyMetadata(
}
}

if (options.getContinuousProfilesSampleRate() == 1.0) {
final double continuousProfilesSampleRate =
readDouble(metadata, logger, CONTINUOUS_PROFILES_SAMPLE_RATE);
if (continuousProfilesSampleRate != -1) {
options.setContinuousProfilesSampleRate(continuousProfilesSampleRate);
}
}

options.setEnableUserInteractionTracing(
readBool(metadata, logger, TRACES_UI_ENABLE, options.isEnableUserInteractionTracing()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ private void createAndStartContinuousProfiler(
final @NotNull Context context,
final @NotNull SentryAppStartProfilingOptions profilingOptions,
final @NotNull AppStartMetrics appStartMetrics) {

if (!profilingOptions.isContinuousProfileSampled()) {
logger.log(SentryLevel.DEBUG, "App start profiling was not sampled. It will not start.");
return;
}

final @NotNull IContinuousProfiler appStartContinuousProfiler =
new AndroidContinuousProfiler(
buildInfoProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,47 @@ class ManifestMetadataReaderTest {
assertNull(fixture.options.profilesSampleRate)
}

@Test
fun `applyMetadata reads continuousProfilesSampleRate from metadata`() {
// Arrange
val expectedSampleRate = 0.99f
val bundle = bundleOf(ManifestMetadataReader.CONTINUOUS_PROFILES_SAMPLE_RATE to expectedSampleRate)
val context = fixture.getContext(metaData = bundle)

// Act
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

// Assert
assertEquals(expectedSampleRate.toDouble(), fixture.options.continuousProfilesSampleRate)
}

@Test
fun `applyMetadata does not override continuousProfilesSampleRate from options`() {
// Arrange
val expectedSampleRate = 0.99f
fixture.options.continuousProfilesSampleRate = expectedSampleRate.toDouble()
val bundle = bundleOf(ManifestMetadataReader.CONTINUOUS_PROFILES_SAMPLE_RATE to 0.1f)
val context = fixture.getContext(metaData = bundle)

// Act
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

// Assert
assertEquals(expectedSampleRate.toDouble(), fixture.options.continuousProfilesSampleRate)
}

@Test
fun `applyMetadata without specifying continuousProfilesSampleRate, stays 1`() {
// Arrange
val context = fixture.getContext()

// Act
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

// Assert
assertEquals(1.0, fixture.options.continuousProfilesSampleRate)
}

@Test
fun `applyMetadata reads tracePropagationTargets to options`() {
// Arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ class SentryPerformanceProviderTest {
)
}

@Test
fun `when continuous profile is not sampled, continuous profiler is not started`() {
fixture.getSut { config ->
writeConfig(config, continuousProfileSampled = false)
}
assertNull(AppStartMetrics.getInstance().appStartProfiler)
assertNull(AppStartMetrics.getInstance().appStartContinuousProfiler)
verify(fixture.logger).log(
eq(SentryLevel.DEBUG),
eq("App start profiling was not sampled. It will not start.")
)
}

// This case should never happen in reality, but it's technically possible to have such configuration
@Test
fun `when both transaction and continuous profilers are enabled, only continuous profiler is created`() {
Expand Down Expand Up @@ -331,6 +344,7 @@ class SentryPerformanceProviderTest {
traceSampleRate: Double = 1.0,
profileSampled: Boolean = true,
profileSampleRate: Double = 1.0,
continuousProfileSampled: Boolean = true,
profilingTracesDirPath: String = traceDir.absolutePath
) {
val appStartProfilingOptions = SentryAppStartProfilingOptions()
Expand All @@ -340,6 +354,7 @@ class SentryPerformanceProviderTest {
appStartProfilingOptions.traceSampleRate = traceSampleRate
appStartProfilingOptions.isProfileSampled = profileSampled
appStartProfilingOptions.profileSampleRate = profileSampleRate
appStartProfilingOptions.isContinuousProfileSampled = continuousProfileSampled
appStartProfilingOptions.profilingTracesDirPath = profilingTracesDirPath
appStartProfilingOptions.profilingTracesHz = 101
JsonSerializer(SentryOptions.empty()).serialize(appStartProfilingOptions, FileWriter(configFile))
Expand Down
9 changes: 9 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ public final class io/sentry/ExternalOptions {
public static fun from (Lio/sentry/config/PropertiesProvider;Lio/sentry/ILogger;)Lio/sentry/ExternalOptions;
public fun getBundleIds ()Ljava/util/Set;
public fun getContextTags ()Ljava/util/List;
public fun getContinuousProfilesSampleRate ()Ljava/lang/Double;
public fun getCron ()Lio/sentry/SentryOptions$Cron;
public fun getDebug ()Ljava/lang/Boolean;
public fun getDist ()Ljava/lang/String;
Expand Down Expand Up @@ -491,6 +492,7 @@ public final class io/sentry/ExternalOptions {
public fun isGlobalHubMode ()Ljava/lang/Boolean;
public fun isSendDefaultPii ()Ljava/lang/Boolean;
public fun isSendModules ()Ljava/lang/Boolean;
public fun setContinuousProfilesSampleRate (Ljava/lang/Double;)V
public fun setCron (Lio/sentry/SentryOptions$Cron;)V
public fun setDebug (Ljava/lang/Boolean;)V
public fun setDist (Ljava/lang/String;)V
Expand Down Expand Up @@ -2488,11 +2490,13 @@ public final class io/sentry/SentryAppStartProfilingOptions : io/sentry/JsonSeri
public fun getProfilingTracesHz ()I
public fun getTraceSampleRate ()Ljava/lang/Double;
public fun getUnknown ()Ljava/util/Map;
public fun isContinuousProfileSampled ()Z
public fun isContinuousProfilingEnabled ()Z
public fun isProfileSampled ()Z
public fun isProfilingEnabled ()Z
public fun isTraceSampled ()Z
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V
public fun setContinuousProfileSampled (Z)V
public fun setContinuousProfilingEnabled (Z)V
public fun setProfileSampleRate (Ljava/lang/Double;)V
public fun setProfileSampled (Z)V
Expand All @@ -2511,6 +2515,7 @@ public final class io/sentry/SentryAppStartProfilingOptions$Deserializer : io/se
}

public final class io/sentry/SentryAppStartProfilingOptions$JsonKeys {
public static final field CONTINUOUS_PROFILE_SAMPLED Ljava/lang/String;
public static final field IS_CONTINUOUS_PROFILING_ENABLED Ljava/lang/String;
public static final field IS_PROFILING_ENABLED Ljava/lang/String;
public static final field PROFILE_SAMPLED Ljava/lang/String;
Expand Down Expand Up @@ -2944,6 +2949,7 @@ public class io/sentry/SentryOptions {
public fun getConnectionTimeoutMillis ()I
public fun getContextTags ()Ljava/util/List;
public fun getContinuousProfiler ()Lio/sentry/IContinuousProfiler;
public fun getContinuousProfilesSampleRate ()D
public fun getCron ()Lio/sentry/SentryOptions$Cron;
public fun getDateProvider ()Lio/sentry/SentryDateProvider;
public fun getDebugMetaLoader ()Lio/sentry/internal/debugmeta/IDebugMetaLoader;
Expand Down Expand Up @@ -3060,6 +3066,7 @@ public class io/sentry/SentryOptions {
public fun setConnectionStatusProvider (Lio/sentry/IConnectionStatusProvider;)V
public fun setConnectionTimeoutMillis (I)V
public fun setContinuousProfiler (Lio/sentry/IContinuousProfiler;)V
public fun setContinuousProfilesSampleRate (D)V
public fun setCron (Lio/sentry/SentryOptions$Cron;)V
public fun setDateProvider (Lio/sentry/SentryDateProvider;)V
public fun setDebug (Z)V
Expand Down Expand Up @@ -3759,6 +3766,7 @@ public final class io/sentry/TraceContext$JsonKeys {
public final class io/sentry/TracesSampler {
public fun <init> (Lio/sentry/SentryOptions;)V
public fun sample (Lio/sentry/SamplingContext;)Lio/sentry/TracesSamplingDecision;
public fun sampleContinuousProfile ()Z
}

public final class io/sentry/TracesSamplingDecision {
Expand Down Expand Up @@ -6316,6 +6324,7 @@ public final class io/sentry/util/Random : java/io/Serializable {

public final class io/sentry/util/SampleRateUtils {
public fun <init> ()V
public static fun isValidContinuousProfilesSampleRate (D)Z
public static fun isValidProfilesSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
Expand Down
11 changes: 11 additions & 0 deletions sentry/src/main/java/io/sentry/ExternalOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public final class ExternalOptions {
private @Nullable Boolean enableDeduplication;
private @Nullable Double tracesSampleRate;
private @Nullable Double profilesSampleRate;
private @Nullable Double continuousProfilesSampleRate;
private @Nullable SentryOptions.RequestSize maxRequestBodySize;
private final @NotNull Map<String, @NotNull String> tags = new ConcurrentHashMap<>();
private @Nullable SentryOptions.Proxy proxy;
Expand Down Expand Up @@ -73,6 +74,8 @@ public final class ExternalOptions {
propertiesProvider.getBooleanProperty("uncaught.handler.print-stacktrace"));
options.setTracesSampleRate(propertiesProvider.getDoubleProperty("traces-sample-rate"));
options.setProfilesSampleRate(propertiesProvider.getDoubleProperty("profiles-sample-rate"));
options.setContinuousProfilesSampleRate(
propertiesProvider.getDoubleProperty("continuous-profiles-sample-rate"));
options.setDebug(propertiesProvider.getBooleanProperty("debug"));
options.setEnableDeduplication(propertiesProvider.getBooleanProperty("enable-deduplication"));
options.setSendClientReports(propertiesProvider.getBooleanProperty("send-client-reports"));
Expand Down Expand Up @@ -284,6 +287,14 @@ public void setProfilesSampleRate(final @Nullable Double profilesSampleRate) {
this.profilesSampleRate = profilesSampleRate;
}

public @Nullable Double getContinuousProfilesSampleRate() {
return continuousProfilesSampleRate;
}

public void setContinuousProfilesSampleRate(final @Nullable Double continuousProfilesSampleRate) {
this.continuousProfilesSampleRate = continuousProfilesSampleRate;
}

public @Nullable SentryOptions.RequestSize getMaxRequestBodySize() {
return maxRequestBodySize;
}
Expand Down
12 changes: 9 additions & 3 deletions sentry/src/main/java/io/sentry/Scopes.java
Original file line number Diff line number Diff line change
Expand Up @@ -926,9 +926,15 @@ public void flush(long timeoutMillis) {
@Override
public void startProfiler() {
if (getOptions().isContinuousProfilingEnabled()) {
getOptions().getLogger().log(SentryLevel.DEBUG, "Started continuous Profiling.");
getOptions().getContinuousProfiler().start();
} else {
if (getOptions().getInternalTracesSampler().sampleContinuousProfile()) {
getOptions().getLogger().log(SentryLevel.DEBUG, "Started continuous Profiling.");
getOptions().getContinuousProfiler().start();
} else {
getOptions()
.getLogger()
.log(SentryLevel.DEBUG, "Profiler was not started due to sampling decision.");
}
} else if (getOptions().isProfilingEnabled()) {
getOptions()
.getLogger()
.log(
Expand Down
3 changes: 2 additions & 1 deletion sentry/src/main/java/io/sentry/Sentry.java
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,8 @@ private static void initConfigurations(final @NotNull SentryOptions options) {
}

final String profilingTracesDirPath = options.getProfilingTracesDirPath();
if (options.isProfilingEnabled() && profilingTracesDirPath != null) {
if ((options.isProfilingEnabled() || options.isContinuousProfilingEnabled())
&& profilingTracesDirPath != null) {

final File profilingTracesDir = new File(profilingTracesDirPath);
profilingTracesDir.mkdirs();
Expand Down
19 changes: 19 additions & 0 deletions sentry/src/main/java/io/sentry/SentryAppStartProfilingOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public final class SentryAppStartProfilingOptions implements JsonUnknown, JsonSe
boolean isProfilingEnabled;
boolean isContinuousProfilingEnabled;
int profilingTracesHz;
boolean continuousProfileSampled;

private @Nullable Map<String, Object> unknown;

Expand All @@ -29,6 +30,7 @@ public SentryAppStartProfilingOptions() {
traceSampleRate = null;
profileSampled = false;
profileSampleRate = null;
continuousProfileSampled = false;
profilingTracesDirPath = null;
isProfilingEnabled = false;
isContinuousProfilingEnabled = false;
Expand All @@ -42,6 +44,7 @@ public SentryAppStartProfilingOptions() {
traceSampleRate = samplingDecision.getSampleRate();
profileSampled = samplingDecision.getProfileSampled();
profileSampleRate = samplingDecision.getProfileSampleRate();
continuousProfileSampled = options.getInternalTracesSampler().sampleContinuousProfile();
profilingTracesDirPath = options.getProfilingTracesDirPath();
isProfilingEnabled = options.isProfilingEnabled();
isContinuousProfilingEnabled = options.isContinuousProfilingEnabled();
Expand All @@ -56,6 +59,14 @@ public boolean isProfileSampled() {
return profileSampled;
}

public void setContinuousProfileSampled(boolean continuousProfileSampled) {
this.continuousProfileSampled = continuousProfileSampled;
}

public boolean isContinuousProfileSampled() {
return continuousProfileSampled;
}

public void setProfileSampleRate(final @Nullable Double profileSampleRate) {
this.profileSampleRate = profileSampleRate;
}
Expand Down Expand Up @@ -117,6 +128,7 @@ public int getProfilingTracesHz() {
public static final class JsonKeys {
public static final String PROFILE_SAMPLED = "profile_sampled";
public static final String PROFILE_SAMPLE_RATE = "profile_sample_rate";
public static final String CONTINUOUS_PROFILE_SAMPLED = "continuous_profile_sampled";
public static final String TRACE_SAMPLED = "trace_sampled";
public static final String TRACE_SAMPLE_RATE = "trace_sample_rate";
public static final String PROFILING_TRACES_DIR_PATH = "profiling_traces_dir_path";
Expand All @@ -131,6 +143,7 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger
writer.beginObject();
writer.name(JsonKeys.PROFILE_SAMPLED).value(logger, profileSampled);
writer.name(JsonKeys.PROFILE_SAMPLE_RATE).value(logger, profileSampleRate);
writer.name(JsonKeys.CONTINUOUS_PROFILE_SAMPLED).value(logger, continuousProfileSampled);
writer.name(JsonKeys.TRACE_SAMPLED).value(logger, traceSampled);
writer.name(JsonKeys.TRACE_SAMPLE_RATE).value(logger, traceSampleRate);
writer.name(JsonKeys.PROFILING_TRACES_DIR_PATH).value(logger, profilingTracesDirPath);
Expand Down Expand Up @@ -186,6 +199,12 @@ public static final class Deserializer
options.profileSampleRate = profileSampleRate;
}
break;
case JsonKeys.CONTINUOUS_PROFILE_SAMPLED:
Boolean continuousProfileSampled = reader.nextBooleanOrNull();
if (continuousProfileSampled != null) {
options.continuousProfileSampled = continuousProfileSampled;
}
break;
case JsonKeys.TRACE_SAMPLED:
Boolean traceSampled = reader.nextBooleanOrNull();
if (traceSampled != null) {
Expand Down
Loading
Loading