diff --git a/CHANGELOG.md b/CHANGELOG.md index 21ef19b0ce..15204b1e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java index 02f9a2c072..830931e717 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java @@ -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 { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java index a895a4bbf4..bd766281f3 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java @@ -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"; @@ -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())); diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java index 8f8318db3d..a3256f692e 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java @@ -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; diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt index 6042546809..0e63104948 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt @@ -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() fixture.options.tracesSampleRate = null fixture.options.isEnableAutoTraceIdGeneration = true - fixture.options.isEnableSessionTraceLifecycle = true + fixture.options.isEnableSessionTraces = true val argumentCaptor: ArgumentCaptor = ArgumentCaptor.forClass(ScopeCallback::class.java) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt index 0d28802858..ca7f5c5898 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt @@ -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 diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerTracingTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerTracingTest.kt index 2178d4a53f..568bff77a1 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerTracingTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerTracingTest.kt @@ -63,7 +63,7 @@ class SentryGestureListenerTracingTest { isEnableUserInteractionTracing: Boolean = true, transaction: SentryTracer? = null, isEnableAutoTraceIdGeneration: Boolean = true, - isEnableSessionTraceLifecycle: Boolean = false, + isEnableSessionTraces: Boolean = false, ): SentryGestureListener { options.tracesSampleRate = tracesSampleRate options.isEnableUserInteractionTracing = isEnableUserInteractionTracing @@ -71,7 +71,7 @@ class SentryGestureListenerTracingTest { options.gestureTargetLocators = listOf(AndroidViewGestureTargetLocator(LazyEvaluator { true })) options.isEnableAutoTraceIdGeneration = isEnableAutoTraceIdGeneration - options.isEnableSessionTraceLifecycle = isEnableSessionTraceLifecycle + options.isEnableSessionTraces = isEnableSessionTraces whenever(scopes.options).thenReturn(options) @@ -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( tracesSampleRate = null, isEnableAutoTraceIdGeneration = true, - isEnableSessionTraceLifecycle = true, + isEnableSessionTraces = true, ) val scope = Scope(fixture.options) val initialPropagationContext = scope.propagationContext diff --git a/sentry-android-navigation/src/main/java/io/sentry/android/navigation/SentryNavigationListener.kt b/sentry-android-navigation/src/main/java/io/sentry/android/navigation/SentryNavigationListener.kt index 0a9c4fb51a..58190bfb0e 100644 --- a/sentry-android-navigation/src/main/java/io/sentry/android/navigation/SentryNavigationListener.kt +++ b/sentry-android-navigation/src/main/java/io/sentry/android/navigation/SentryNavigationListener.kt @@ -108,7 +108,7 @@ constructor( arguments: Map, ) { if (!isPerformanceEnabled) { - if (!scopes.options.isEnableSessionTraceLifecycle) { + if (!scopes.options.isEnableSessionTraces) { TracingUtils.startNewTrace(scopes) } return diff --git a/sentry-android-navigation/src/test/java/io/sentry/android/navigation/SentryNavigationListenerTest.kt b/sentry-android-navigation/src/test/java/io/sentry/android/navigation/SentryNavigationListenerTest.kt index 9320563be1..c46e83df4a 100644 --- a/sentry-android-navigation/src/test/java/io/sentry/android/navigation/SentryNavigationListenerTest.kt +++ b/sentry-android-navigation/src/test/java/io/sentry/android/navigation/SentryNavigationListenerTest.kt @@ -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) @@ -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 = ArgumentCaptor.forClass(ScopeCallback::class.java) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 069c55ab26..e8eabfc020 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -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; @@ -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 @@ -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 @@ -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 diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java index b974c575d2..07b2ac8e16 100644 --- a/sentry/src/main/java/io/sentry/ExternalOptions.java +++ b/sentry/src/main/java/io/sentry/ExternalOptions.java @@ -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; @@ -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")); @@ -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() { diff --git a/sentry/src/main/java/io/sentry/Scopes.java b/sentry/src/main/java/io/sentry/Scopes.java index 5e55fa9877..1140b07086 100644 --- a/sentry/src/main/java/io/sentry/Scopes.java +++ b/sentry/src/main/java/io/sentry/Scopes.java @@ -388,7 +388,7 @@ public void startSession() { getClient().captureSession(pair.getPrevious(), hint); } - if (getOptions().isEnableSessionTraceLifecycle()) { + if (getOptions().isEnableSessionTraces()) { configureScope(scope -> scope.setPropagationContext(new PropagationContext())); } @@ -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( @@ -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 = diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index c3bc7fcd4a..4ec6f4d00e 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -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 @@ -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. * *

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 @@ -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. * *

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; } /** @@ -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()); diff --git a/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt b/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt index f7e716d917..6436382140 100644 --- a/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/ExternalOptionsTest.kt @@ -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) } } } diff --git a/sentry/src/test/java/io/sentry/ScopesTest.kt b/sentry/src/test/java/io/sentry/ScopesTest.kt index 0467411dd7..11d39efb7c 100644 --- a/sentry/src/test/java/io/sentry/ScopesTest.kt +++ b/sentry/src/test/java/io/sentry/ScopesTest.kt @@ -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") @@ -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() @@ -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() @@ -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() @@ -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" } diff --git a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt index a85ab8c5a5..346868353a 100644 --- a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt @@ -50,8 +50,8 @@ class SentryOptionsTest { } @Test - fun `when options is initialized, session trace lifecycle is disabled`() { - assertFalse(SentryOptions().isEnableSessionTraceLifecycle) + fun `when options is initialized, session traces are disabled`() { + assertFalse(SentryOptions().isEnableSessionTraces) } @Test @@ -425,7 +425,7 @@ class SentryOptionsTest { externalOptions.profileSessionSampleRate = 0.8 externalOptions.profilingTracesDirPath = "/profiling-traces" externalOptions.profileLifecycle = ProfileLifecycle.TRACE - externalOptions.isEnableSessionTraceLifecycle = true + externalOptions.isEnableSessionTraces = true val hash = StringUtils.calculateStringHash(externalOptions.dsn, mock()) val options = SentryOptions() @@ -490,7 +490,7 @@ class SentryOptionsTest { assertEquals(0.8, options.profileSessionSampleRate) assertEquals("/profiling-traces${File.separator}${hash}", options.profilingTracesDirPath) assertEquals(ProfileLifecycle.TRACE, options.profileLifecycle) - assertTrue(options.isEnableSessionTraceLifecycle) + assertTrue(options.isEnableSessionTraces) } @Test