Skip to content
Open
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

## Unreleased

### Internal
### Performance

- Probe class availability without initializing the class during SDK init ([#5635](https://github.com/getsentry/sentry-java/pull/5635))
- Cache reflective class lookups and avoid double-probing during SDK init ([#5636](https://github.com/getsentry/sentry-java/pull/5636))
- Only probe for Compose classes during init when user interaction tracking or view hierarchy capture is enabled ([#5637](https://github.com/getsentry/sentry-java/pull/5637))

## 8.45.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,18 @@ static void initializeIntegrationsAndProcessors(

final @NotNull LazyEvaluator<Boolean> isAndroidXScrollViewAvailable =
loadClass.isClassAvailableLazy("androidx.core.view.ScrollingView", options);
final boolean isComposeUpstreamAvailable =
loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options);

if (options.getGestureTargetLocators().isEmpty()) {
// Gated behind the features that actually consume these so the Compose class lookups only run
// when user interaction tracking or view hierarchy capture is enabled. Repeated COMPOSE_CLASS
// probes across both blocks are deduplicated by LoadClass's cache.
final boolean isUserInteractionEnabled =
options.isEnableUserInteractionBreadcrumbs() || options.isEnableUserInteractionTracing();
if (isUserInteractionEnabled && options.getGestureTargetLocators().isEmpty()) {
final List<GestureTargetLocator> gestureTargetLocators = new ArrayList<>(2);
gestureTargetLocators.add(new AndroidViewGestureTargetLocator(isAndroidXScrollViewAvailable));

final boolean isComposeAvailable =
(isComposeUpstreamAvailable
(loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options)
&& loadClass.isClassAvailable(
SENTRY_COMPOSE_GESTURE_INTEGRATION_CLASS_NAME, options));

Expand All @@ -229,8 +232,9 @@ static void initializeIntegrationsAndProcessors(
options.setGestureTargetLocators(gestureTargetLocators);
}

if (options.getViewHierarchyExporters().isEmpty()
&& isComposeUpstreamAvailable
if (options.isAttachViewHierarchy()
&& options.getViewHierarchyExporters().isEmpty()
&& loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options)
&& loadClass.isClassAvailable(
SENTRY_COMPOSE_VIEW_HIERARCHY_INTEGRATION_CLASS_NAME, options)) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,51 @@ class AndroidOptionsInitializerTest {
assertTrue { fixture.sentryOptions.gestureTargetLocators[1] is ComposeGestureTargetLocator }
}

@Test
fun `does not set gesture target locators when user interaction tracking is disabled`() {
fixture.sentryOptions.isEnableUserInteractionBreadcrumbs = false
fixture.sentryOptions.isEnableUserInteractionTracing = false

fixture.initSutWithClassLoader(
classesToLoad =
listOf(
AndroidOptionsInitializer.COMPOSE_CLASS_NAME,
AndroidOptionsInitializer.SENTRY_COMPOSE_GESTURE_INTEGRATION_CLASS_NAME,
)
)

assertTrue { fixture.sentryOptions.gestureTargetLocators.isEmpty() }
}

@Test
fun `does not set compose view hierarchy exporter when attachViewHierarchy is disabled`() {
// attachViewHierarchy defaults to false
fixture.initSutWithClassLoader(
classesToLoad =
listOf(
AndroidOptionsInitializer.COMPOSE_CLASS_NAME,
AndroidOptionsInitializer.SENTRY_COMPOSE_VIEW_HIERARCHY_INTEGRATION_CLASS_NAME,
)
)

assertTrue { fixture.sentryOptions.viewHierarchyExporters.isEmpty() }
}

@Test
fun `sets compose view hierarchy exporter when attachViewHierarchy is enabled and compose is available`() {
fixture.sentryOptions.isAttachViewHierarchy = true

fixture.initSutWithClassLoader(
classesToLoad =
listOf(
AndroidOptionsInitializer.COMPOSE_CLASS_NAME,
AndroidOptionsInitializer.SENTRY_COMPOSE_VIEW_HIERARCHY_INTEGRATION_CLASS_NAME,
)
)

assertTrue { fixture.sentryOptions.viewHierarchyExporters.size == 1 }
}

@Test
fun `AndroidMemoryCollector is set to options`() {
fixture.initSut()
Expand Down
Loading