Skip to content
Draft
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Features

- Add opt-in Android session trace lifecycle support ([#5398](https://github.com/getsentry/sentry-java/pull/5398))
- Add opt-in Android session tracing support ([#5398](https://github.com/getsentry/sentry-java/pull/5398))

## 8.41.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private void startTracing(final @NotNull Activity activity) {
if (scopes != null && !isRunningTransactionOrTrace(activity)) {
if (!performanceEnabled) {
activitiesWithOngoingTransactions.put(activity, NoOpTransaction.getInstance());
if (options.isEnableAutoTraceIdGeneration() && !options.isEnableSessionTraceLifecycle()) {
if (options.isEnableAutoTraceIdGeneration() && !options.isEnableSessionTraces()) {
TracingUtils.startNewTrace(scopes);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ final class ManifestMetadataReader {
static final String ENABLE_AUTO_TRACE_ID_GENERATION =
"io.sentry.traces.enable-auto-id-generation";

static final String ENABLE_SESSION_TRACE_LIFECYCLE =
"io.sentry.traces.enable-session-trace-lifecycle";
static final String ENABLE_SESSION_TRACES = "io.sentry.traces.enable-session-traces";

static final String DEADLINE_TIMEOUT = "io.sentry.traces.deadline-timeout";

Expand Down Expand Up @@ -513,12 +512,8 @@ static void applyMetadata(
ENABLE_AUTO_TRACE_ID_GENERATION,
options.isEnableAutoTraceIdGeneration()));

options.setEnableSessionTraceLifecycle(
readBool(
metadata,
logger,
ENABLE_SESSION_TRACE_LIFECYCLE,
options.isEnableSessionTraceLifecycle()));
options.setEnableSessionTraces(
readBool(metadata, logger, ENABLE_SESSION_TRACES, options.isEnableSessionTraces()));

options.setDeadlineTimeout(
readLong(metadata, logger, DEADLINE_TIMEOUT, options.getDeadlineTimeout()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private void startTracing(final @NotNull UiElement target, final @NotNull Gestur

if (!(options.isTracingEnabled() && options.isEnableUserInteractionTracing())) {
if (isNewInteraction) {
if (options.isEnableAutoTraceIdGeneration() && !options.isEnableSessionTraceLifecycle()) {
if (options.isEnableAutoTraceIdGeneration() && !options.isEnableSessionTraces()) {
TracingUtils.startNewTrace(scopes);
}
activeUiElement = target;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1414,12 +1414,12 @@ class ActivityLifecycleIntegrationTest {
}

@Test
fun `does not start a new trace if performance is disabled and session trace lifecycle is enabled`() {
fun `does not start a new trace if performance is disabled and session traces are enabled`() {
val sut = fixture.getSut()
val activity = mock<Activity>()
fixture.options.tracesSampleRate = null
fixture.options.isEnableAutoTraceIdGeneration = true
fixture.options.isEnableSessionTraceLifecycle = true
fixture.options.isEnableSessionTraces = true

val argumentCaptor: ArgumentCaptor<ScopeCallback> =
ArgumentCaptor.forClass(ScopeCallback::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ class ManifestMetadataReaderTest {
}

@Test
fun `applyMetadata reads session trace lifecycle to options`() {
val bundle = bundleOf(ManifestMetadataReader.ENABLE_SESSION_TRACE_LIFECYCLE to true)
fun `applyMetadata reads session traces to options`() {
val bundle = bundleOf(ManifestMetadataReader.ENABLE_SESSION_TRACES to true)
val context = fixture.getContext(metaData = bundle)

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

assertTrue(fixture.options.isEnableSessionTraceLifecycle)
assertTrue(fixture.options.isEnableSessionTraces)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ class SentryGestureListenerTracingTest {
isEnableUserInteractionTracing: Boolean = true,
transaction: SentryTracer? = null,
isEnableAutoTraceIdGeneration: Boolean = true,
isEnableSessionTraceLifecycle: Boolean = false,
isEnableSessionTraces: Boolean = false,
): SentryGestureListener {
options.tracesSampleRate = tracesSampleRate
options.isEnableUserInteractionTracing = isEnableUserInteractionTracing
options.isEnableUserInteractionBreadcrumbs = true
options.gestureTargetLocators =
listOf(AndroidViewGestureTargetLocator(LazyEvaluator { true }))
options.isEnableAutoTraceIdGeneration = isEnableAutoTraceIdGeneration
options.isEnableSessionTraceLifecycle = isEnableSessionTraceLifecycle
options.isEnableSessionTraces = isEnableSessionTraces

whenever(scopes.options).thenReturn(options)

Expand Down Expand Up @@ -402,12 +402,12 @@ class SentryGestureListenerTracingTest {
}

@Test
fun `when tracing is disabled and session trace lifecycle is enabled, does not start a new trace`() {
fun `when tracing is disabled and session traces are enabled, does not start a new trace`() {
val sut =
fixture.getSut<View>(
tracesSampleRate = null,
isEnableAutoTraceIdGeneration = true,
isEnableSessionTraceLifecycle = true,
isEnableSessionTraces = true,
)
val scope = Scope(fixture.options)
val initialPropagationContext = scope.propagationContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ constructor(
arguments: Map<String, Any?>,
) {
if (!isPerformanceEnabled) {
if (!scopes.options.isEnableSessionTraceLifecycle) {
if (!scopes.options.isEnableSessionTraces) {
TracingUtils.startNewTrace(scopes)
}
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ class SentryNavigationListenerTest {
hasViewIdInRes: Boolean = true,
transaction: SentryTracer? = null,
traceOriginAppendix: String? = null,
enableSessionTraceLifecycle: Boolean = false,
enableSessionTraces: Boolean = false,
): SentryNavigationListener {
options =
SentryOptions().apply {
dsn = "http://key@localhost/proj"
setTracesSampleRate(tracesSampleRate)
isEnableScreenTracking = enableScreenTracking
isEnableSessionTraceLifecycle = enableSessionTraceLifecycle
isEnableSessionTraces = enableSessionTraces
}
whenever(scopes.options).thenReturn(options)

Expand Down Expand Up @@ -367,8 +367,8 @@ class SentryNavigationListenerTest {
}

@Test
fun `does not start new trace if performance is disabled and session trace lifecycle is enabled`() {
val sut = fixture.getSut(enableNavigationTracing = false, enableSessionTraceLifecycle = true)
fun `does not start new trace if performance is disabled and session traces are enabled`() {
val sut = fixture.getSut(enableNavigationTracing = false, enableSessionTraces = true)

val argumentCaptor: ArgumentCaptor<ScopeCallback> =
ArgumentCaptor.forClass(ScopeCallback::class.java)
Expand Down
8 changes: 4 additions & 4 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public final class io/sentry/ExternalOptions {
public fun isEnableMetrics ()Ljava/lang/Boolean;
public fun isEnablePrettySerializationOutput ()Ljava/lang/Boolean;
public fun isEnableQueueTracing ()Ljava/lang/Boolean;
public fun isEnableSessionTraceLifecycle ()Ljava/lang/Boolean;
public fun isEnableSessionTraces ()Ljava/lang/Boolean;
public fun isEnableSpotlight ()Ljava/lang/Boolean;
public fun isEnabled ()Ljava/lang/Boolean;
public fun isForceInit ()Ljava/lang/Boolean;
Expand All @@ -551,7 +551,7 @@ public final class io/sentry/ExternalOptions {
public fun setEnableMetrics (Ljava/lang/Boolean;)V
public fun setEnablePrettySerializationOutput (Ljava/lang/Boolean;)V
public fun setEnableQueueTracing (Ljava/lang/Boolean;)V
public fun setEnableSessionTraceLifecycle (Ljava/lang/Boolean;)V
public fun setEnableSessionTraces (Ljava/lang/Boolean;)V
public fun setEnableSpotlight (Ljava/lang/Boolean;)V
public fun setEnableUncaughtExceptionHandler (Ljava/lang/Boolean;)V
public fun setEnabled (Ljava/lang/Boolean;)V
Expand Down Expand Up @@ -3721,7 +3721,7 @@ public class io/sentry/SentryOptions {
public fun isEnableQueueTracing ()Z
public fun isEnableScopePersistence ()Z
public fun isEnableScreenTracking ()Z
public fun isEnableSessionTraceLifecycle ()Z
public fun isEnableSessionTraces ()Z
public fun isEnableShutdownHook ()Z
public fun isEnableSpotlight ()Z
public fun isEnableTimeToFullDisplayTracing ()Z
Expand Down Expand Up @@ -3783,7 +3783,7 @@ public class io/sentry/SentryOptions {
public fun setEnableQueueTracing (Z)V
public fun setEnableScopePersistence (Z)V
public fun setEnableScreenTracking (Z)V
public fun setEnableSessionTraceLifecycle (Z)V
public fun setEnableSessionTraces (Z)V
public fun setEnableShutdownHook (Z)V
public fun setEnableSpotlight (Z)V
public fun setEnableTimeToFullDisplayTracing (Z)V
Expand Down
13 changes: 6 additions & 7 deletions sentry/src/main/java/io/sentry/ExternalOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public final class ExternalOptions {
private @Nullable ProfileLifecycle profileLifecycle;

private @Nullable Boolean strictTraceContinuation;
private @Nullable Boolean enableSessionTraceLifecycle;
private @Nullable Boolean enableSessionTraces;
private @Nullable String orgId;

private @Nullable SentryOptions.Cron cron;
Expand Down Expand Up @@ -230,8 +230,7 @@ public final class ExternalOptions {

options.setStrictTraceContinuation(
propertiesProvider.getBooleanProperty("enable-strict-trace-continuation"));
options.setEnableSessionTraceLifecycle(
propertiesProvider.getBooleanProperty("enable-session-trace-lifecycle"));
options.setEnableSessionTraces(propertiesProvider.getBooleanProperty("enable-session-traces"));
options.setOrgId(propertiesProvider.getProperty("org-id"));

options.setEnableSpotlight(propertiesProvider.getBooleanProperty("enable-spotlight"));
Expand Down Expand Up @@ -650,12 +649,12 @@ public void setStrictTraceContinuation(final @Nullable Boolean strictTraceContin
this.strictTraceContinuation = strictTraceContinuation;
}

public @Nullable Boolean isEnableSessionTraceLifecycle() {
return enableSessionTraceLifecycle;
public @Nullable Boolean isEnableSessionTraces() {
return enableSessionTraces;
}

public void setEnableSessionTraceLifecycle(final @Nullable Boolean enableSessionTraceLifecycle) {
this.enableSessionTraceLifecycle = enableSessionTraceLifecycle;
public void setEnableSessionTraces(final @Nullable Boolean enableSessionTraces) {
this.enableSessionTraces = enableSessionTraces;
}

public @Nullable String getOrgId() {
Expand Down
8 changes: 4 additions & 4 deletions sentry/src/main/java/io/sentry/Scopes.java
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ public void startSession() {
getClient().captureSession(pair.getPrevious(), hint);
}

if (getOptions().isEnableSessionTraceLifecycle()) {
if (getOptions().isEnableSessionTraces()) {
configureScope(scope -> scope.setPropagationContext(new PropagationContext()));
}

Expand Down Expand Up @@ -962,7 +962,7 @@ public void flush(long timeoutMillis) {
transaction = NoOpTransaction.getInstance();
} else {
final @NotNull TransactionContext effectiveTransactionContext =
maybeApplySessionTraceLifecycle(transactionContext);
maybeApplySessionTraces(transactionContext);
final Double sampleRand = getSampleRand(effectiveTransactionContext);
final SamplingContext samplingContext =
new SamplingContext(
Expand Down Expand Up @@ -1022,9 +1022,9 @@ && getOptions().getProfileLifecycle() == ProfileLifecycle.TRACE
return transaction;
}

private @NotNull TransactionContext maybeApplySessionTraceLifecycle(
private @NotNull TransactionContext maybeApplySessionTraces(
final @NotNull TransactionContext transactionContext) {
if (getOptions().isEnableSessionTraceLifecycle()
if (getOptions().isEnableSessionTraces()
&& transactionContext.getParentSpanId() == null
&& getCombinedScopeView().getSession() != null) {
final @NotNull PropagationContext propagationContext =
Expand Down
24 changes: 12 additions & 12 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ public class SentryOptions {
/** Whether to enable or disable automatic session tracking. */
private boolean enableAutoSessionTracking = true;

/** Whether root transactions should reuse the current session trace lifecycle. */
private boolean enableSessionTraceLifecycle = false;
/** Whether root transactions should reuse the current session trace. */
private boolean enableSessionTraces = false;

/**
* The session tracking interval in millis. This is the interval to end a session if the App goes
Expand Down Expand Up @@ -1422,7 +1422,7 @@ public void setEnableAutoSessionTracking(final boolean enableAutoSessionTracking
}

/**
* Returns whether root transactions should reuse the current session trace lifecycle.
* Returns whether root transactions should reuse the current session trace.
*
* <p>This option is intended for Android/mobile SDKs where trace boundaries are managed by the
* SDK session lifecycle. Do not enable it for JVM backend, desktop, or other non-session-managed
Expand All @@ -1431,23 +1431,23 @@ public void setEnableAutoSessionTracking(final boolean enableAutoSessionTracking
* @return true if enabled or false otherwise
*/
@ApiStatus.Experimental
public boolean isEnableSessionTraceLifecycle() {
return enableSessionTraceLifecycle;
public boolean isEnableSessionTraces() {
return enableSessionTraces;
}

/**
* Enables or disables session trace lifecycle. When enabled, root transactions without a parent
* span can reuse the current session propagation context.
* Enables or disables session traces. When enabled, root transactions without a parent span can
* reuse the current session propagation context.
*
* <p>This option is intended for Android/mobile SDKs where trace boundaries are managed by the
* SDK session lifecycle. Do not enable it for JVM backend, desktop, or other non-session-managed
* runtimes because unrelated root transactions may otherwise share the same trace.
*
* @param enableSessionTraceLifecycle true if enabled or false otherwise
* @param enableSessionTraces true if enabled or false otherwise
*/
@ApiStatus.Experimental
public void setEnableSessionTraceLifecycle(final boolean enableSessionTraceLifecycle) {
this.enableSessionTraceLifecycle = enableSessionTraceLifecycle;
public void setEnableSessionTraces(final boolean enableSessionTraces) {
this.enableSessionTraces = enableSessionTraces;
}

/**
Expand Down Expand Up @@ -3669,8 +3669,8 @@ public void merge(final @NotNull ExternalOptions options) {
if (options.isStrictTraceContinuation() != null) {
setStrictTraceContinuation(options.isStrictTraceContinuation());
}
if (options.isEnableSessionTraceLifecycle() != null) {
setEnableSessionTraceLifecycle(options.isEnableSessionTraceLifecycle());
if (options.isEnableSessionTraces() != null) {
setEnableSessionTraces(options.isEnableSessionTraces());
}
if (options.getOrgId() != null) {
setOrgId(options.getOrgId());
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/test/java/io/sentry/ExternalOptionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ class ExternalOptionsTest {
}

@Test
fun `creates options with enableSessionTraceLifecycle using external properties`() {
withPropertiesFile("enable-session-trace-lifecycle=true") {
assertNotNull(it.isEnableSessionTraceLifecycle) { assertTrue(it) }
fun `creates options with enableSessionTraces using external properties`() {
withPropertiesFile("enable-session-traces=true") {
assertNotNull(it.isEnableSessionTraces) { assertTrue(it) }
}
}

Expand Down
16 changes: 8 additions & 8 deletions sentry/src/test/java/io/sentry/ScopesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1823,8 +1823,8 @@ class ScopesTest {
}

@Test
fun `when session trace lifecycle is enabled without active session, root transaction does not use scope propagation context`() {
val scopes = generateScopes { it.isEnableSessionTraceLifecycle = true }
fun `when session traces are enabled without active session, root transaction does not use scope propagation context`() {
val scopes = generateScopes { it.isEnableSessionTraces = true }
var propagationContext: PropagationContext? = null
scopes.configureScope { propagationContext = it.propagationContext }
val context = TransactionContext("name", "op")
Expand All @@ -1837,9 +1837,9 @@ class ScopesTest {
}

@Test
fun `when session trace lifecycle is enabled, startTransaction uses session propagation context`() {
fun `when session traces are enabled, startTransaction uses session propagation context`() {
val scopes = generateScopes {
it.isEnableSessionTraceLifecycle = true
it.isEnableSessionTraces = true
it.release = "1.0.0"
}
scopes.startSession()
Expand All @@ -1858,7 +1858,7 @@ class ScopesTest {
@Test
fun `continued trace with parent span is not remapped to session trace`() {
val scopes = generateScopes {
it.isEnableSessionTraceLifecycle = true
it.isEnableSessionTraces = true
it.release = "1.0.0"
}
scopes.startSession()
Expand All @@ -1874,9 +1874,9 @@ class ScopesTest {
}

@Test
fun `when session trace lifecycle is enabled, root transaction uses current propagation context`() {
fun `when session traces are enabled, root transaction uses current propagation context`() {
val scopes = generateScopes {
it.isEnableSessionTraceLifecycle = true
it.isEnableSessionTraces = true
it.release = "1.0.0"
}
scopes.startSession()
Expand All @@ -1895,7 +1895,7 @@ class ScopesTest {
@Test
fun `session trace transaction baggage is populated after scope baggage is frozen`() {
val scopes = generateScopes {
it.isEnableSessionTraceLifecycle = true
it.isEnableSessionTraces = true
it.release = "1.0.0"
it.environment = "production"
}
Expand Down
Loading
Loading