From 38c8af84830359eeb0d58dcf378902e22bee1b72 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Mon, 17 Mar 2025 13:03:36 +0100 Subject: [PATCH 1/3] Do not override user-defined SentryOptions --- .../core/AndroidOptionsInitializer.java | 27 +++++++++++++---- .../core/AndroidOptionsInitializerTest.kt | 30 +++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java index 90b6c5d741e..44ff13ef20e 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java @@ -11,6 +11,7 @@ import io.sentry.ISentryLifecycleToken; import io.sentry.ITransactionProfiler; import io.sentry.NoOpConnectionStatusProvider; +import io.sentry.NoOpTransactionPerformanceCollector; import io.sentry.ScopeType; import io.sentry.SendFireAndForgetEnvelopeSender; import io.sentry.SendFireAndForgetOutboxSender; @@ -32,12 +33,16 @@ import io.sentry.cache.PersistingScopeObserver; import io.sentry.compose.gestures.ComposeGestureTargetLocator; import io.sentry.compose.viewhierarchy.ComposeViewHierarchyExporter; +import io.sentry.internal.debugmeta.NoOpDebugMetaLoader; import io.sentry.internal.gestures.GestureTargetLocator; +import io.sentry.internal.modules.NoOpModulesLoader; import io.sentry.internal.viewhierarchy.ViewHierarchyExporter; import io.sentry.transport.CurrentDateProvider; import io.sentry.transport.NoOpEnvelopeCache; +import io.sentry.transport.NoOpTransportGate; import io.sentry.util.LazyEvaluator; import io.sentry.util.Objects; +import io.sentry.util.thread.NoOpThreadChecker; import java.io.File; import java.util.ArrayList; import java.util.List; @@ -160,7 +165,9 @@ static void initializeIntegrationsAndProcessors( options.addEventProcessor(new ScreenshotEventProcessor(options, buildInfoProvider)); options.addEventProcessor(new ViewHierarchyEventProcessor(options)); options.addEventProcessor(new AnrV2EventProcessor(context, options, buildInfoProvider)); - options.setTransportGate(new AndroidTransportGate(options)); + if (options.getTransportGate() instanceof NoOpTransportGate) { + options.setTransportGate(new AndroidTransportGate(options)); + } // Check if the profiler was already instantiated in the app start. // We use the Android profiler, that uses a global start/stop api, so we need to preserve the @@ -182,8 +189,12 @@ static void initializeIntegrationsAndProcessors( "options.getFrameMetricsCollector is required"))); } } - options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger())); - options.setDebugMetaLoader(new AssetsDebugMetaLoader(context, options.getLogger())); + if (options.getModulesLoader() instanceof NoOpModulesLoader) { + options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger())); + } + if (options.getDebugMetaLoader() instanceof NoOpDebugMetaLoader) { + options.setDebugMetaLoader(new AssetsDebugMetaLoader(context, options.getLogger())); + } final boolean isAndroidXScrollViewAvailable = loadClass.isClassAvailable("androidx.core.view.ScrollingView", options); @@ -215,7 +226,9 @@ static void initializeIntegrationsAndProcessors( options.setViewHierarchyExporters(viewHierarchyExporters); } - options.setThreadChecker(AndroidThreadChecker.getInstance()); + if (options.getThreadChecker() instanceof NoOpThreadChecker) { + options.setThreadChecker(AndroidThreadChecker.getInstance()); + } if (options.getPerformanceCollectors().isEmpty()) { options.addPerformanceCollector(new AndroidMemoryCollector()); options.addPerformanceCollector(new AndroidCpuCollector(options.getLogger())); @@ -229,7 +242,11 @@ static void initializeIntegrationsAndProcessors( "options.getFrameMetricsCollector is required"))); } } - options.setTransactionPerformanceCollector(new DefaultTransactionPerformanceCollector(options)); + if (options.getTransactionPerformanceCollector() + instanceof NoOpTransactionPerformanceCollector) { + options.setTransactionPerformanceCollector( + new DefaultTransactionPerformanceCollector(options)); + } } static void installDefaultIntegrations( diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt index 401e65fa1ab..32c559ac40b 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt @@ -7,20 +7,29 @@ import android.os.Bundle import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import io.sentry.DefaultTransactionPerformanceCollector +import io.sentry.IConnectionStatusProvider import io.sentry.ILogger import io.sentry.MainEventProcessor import io.sentry.SentryOptions +import io.sentry.TransactionPerformanceCollector import io.sentry.android.core.cache.AndroidEnvelopeCache +import io.sentry.android.core.internal.debugmeta.AssetsDebugMetaLoader import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator import io.sentry.android.core.internal.modules.AssetsModulesLoader +import io.sentry.android.core.internal.util.AndroidConnectionStatusProvider import io.sentry.android.core.internal.util.AndroidThreadChecker import io.sentry.android.fragment.FragmentLifecycleIntegration import io.sentry.android.replay.ReplayIntegration import io.sentry.android.timber.SentryTimberIntegration +import io.sentry.cache.IEnvelopeCache import io.sentry.cache.PersistingOptionsObserver import io.sentry.cache.PersistingScopeObserver import io.sentry.compose.gestures.ComposeGestureTargetLocator +import io.sentry.internal.debugmeta.IDebugMetaLoader +import io.sentry.internal.modules.IModulesLoader import io.sentry.test.ImmediateExecutorService +import io.sentry.transport.ITransportGate +import io.sentry.util.thread.IThreadChecker import org.junit.runner.RunWith import org.mockito.kotlin.any import org.mockito.kotlin.eq @@ -732,4 +741,25 @@ class AndroidOptionsInitializerTest { fixture.sentryOptions.findPersistingScopeObserver()?.setTags(mapOf("key" to "value")) assertFalse(File(AndroidOptionsInitializer.getCacheDir(fixture.context), PersistingScopeObserver.SCOPE_CACHE).exists()) } + + @Test + fun `user options have precedence over defaults`() { + fixture.initSut(configureOptions = { + setTransportGate(mock()) + setEnvelopeDiskCache(mock()) + connectionStatusProvider = mock() + setModulesLoader(mock()) + setDebugMetaLoader(mock()) + threadChecker = mock() + transactionPerformanceCollector = mock() + }) + + assertFalse { fixture.sentryOptions.transportGate is AndroidTransportGate } + assertFalse { fixture.sentryOptions.envelopeDiskCache is AndroidEnvelopeCache } + assertFalse { fixture.sentryOptions.connectionStatusProvider is AndroidConnectionStatusProvider } + assertFalse { fixture.sentryOptions.modulesLoader is AssetsModulesLoader } + assertFalse { fixture.sentryOptions.debugMetaLoader is AssetsDebugMetaLoader } + assertFalse { fixture.sentryOptions.threadChecker is AndroidThreadChecker } + assertFalse { fixture.sentryOptions.transactionPerformanceCollector is DefaultTransactionPerformanceCollector } + } } From 929c15f2cba83f68217894741572927cca9a4e8e Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Mon, 17 Mar 2025 13:06:39 +0100 Subject: [PATCH 2/3] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e81bd10e0c..a76d8ec115c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Reduce excessive CPU usage when serializing breadcrumbs to disk for ANRs ([#4181](https://github.com/getsentry/sentry-java/pull/4181)) - Ensure app start type is set, even when ActivityLifecycleIntegration is not running ([#4250](https://github.com/getsentry/sentry-java/pull/4250)) +- Do not override user-defined `SentryOptions` ([#4262](https://github.com/getsentry/sentry-java/pull/4262)) ### Behavioral Changes From 24dc2ac93e5dd0364b065261cbf6cabdba58a63e Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Wed, 19 Mar 2025 17:47:18 +0100 Subject: [PATCH 3/3] Formatting --- .../io/sentry/android/core/AndroidOptionsInitializerTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt index 9aa6f69c53a..dfc88fa0e78 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt @@ -8,8 +8,8 @@ import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import io.sentry.CompositePerformanceCollector import io.sentry.DefaultCompositePerformanceCollector -import io.sentry.IContinuousProfiler import io.sentry.IConnectionStatusProvider +import io.sentry.IContinuousProfiler import io.sentry.ILogger import io.sentry.ITransactionProfiler import io.sentry.MainEventProcessor