Skip to content

Commit 514ac01

Browse files
markushiromtsn
andauthored
fix(android): Prevent repeated scroll target logging by updating scroll state (#4557)
* fix(android): Prevent repeated scroll target logging by updating scrollState.type When ViewUtils.findTarget returns null in SentryGestureListener.onScroll, the code was logging an error but not updating scrollState.type from Unknown. This caused repeated target searches and duplicate log messages on subsequent onScroll calls during the same gesture. The fix sets scrollState.type = GestureType.Scroll even when target is null, preventing repeated search attempts while maintaining existing behavior. Fixes: "Unable to find scroll target. No breadcrumb captured." being logged repeatedly * Update Changelog * Update CHANGELOG.md Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com> * Fix tests --------- Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
1 parent 2bfacef commit 514ac01

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
### Fixes
66

77
- Allow multiple UncaughtExceptionHandlerIntegrations to be active at the same time ([#4462](https://github.com/getsentry/sentry-java/pull/4462))
8+
- Prevent repeated scroll target determination during a single scroll gesture ([#4557](https://github.com/getsentry/sentry-java/pull/4557))
9+
- This should reduce the number of ANRs seen in `SentryGestureListener`
810

911
## 8.17.0
1012

sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ public boolean onScroll(
139139
options
140140
.getLogger()
141141
.log(SentryLevel.DEBUG, "Unable to find scroll target. No breadcrumb captured.");
142+
scrollState.type = GestureType.Scroll;
142143
return false;
143144
} else {
144145
options

sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import android.widget.AbsListView
1111
import android.widget.ListAdapter
1212
import androidx.core.view.ScrollingView
1313
import io.sentry.Breadcrumb
14+
import io.sentry.ILogger
1415
import io.sentry.IScope
1516
import io.sentry.IScopes
1617
import io.sentry.PropagationContext
1718
import io.sentry.Scope
1819
import io.sentry.ScopeCallback
20+
import io.sentry.SentryLevel
1921
import io.sentry.SentryLevel.INFO
2022
import io.sentry.android.core.SentryAndroidOptions
2123
import kotlin.test.Test
@@ -28,6 +30,7 @@ import org.mockito.kotlin.doAnswer
2830
import org.mockito.kotlin.inOrder
2931
import org.mockito.kotlin.mock
3032
import org.mockito.kotlin.never
33+
import org.mockito.kotlin.times
3134
import org.mockito.kotlin.verify
3235
import org.mockito.kotlin.verifyNoMoreInteractions
3336
import org.mockito.kotlin.whenever
@@ -56,7 +59,7 @@ class SentryGestureListenerScrollTest {
5659
val directions = setOf("up", "down", "left", "right")
5760

5861
internal inline fun <reified T : View> getSut(
59-
resourceName: String = "test_scroll_view",
62+
resourceName: String? = "test_scroll_view",
6063
touchWithinBounds: Boolean = true,
6164
direction: String = "",
6265
): SentryGestureListener {
@@ -229,6 +232,22 @@ class SentryGestureListenerScrollTest {
229232
verify(fixture.scope).propagationContext = any()
230233
}
231234

235+
@Test
236+
fun `logs error message only once per gesture when no scroll target is found`() {
237+
val logger = mock<ILogger>()
238+
fixture.options.setLogger(logger)
239+
fixture.options.isDebug = true
240+
val sut = fixture.getSut<ScrollableListView>(resourceName = null)
241+
242+
sut.onDown(fixture.firstEvent)
243+
fixture.eventsInBetween.forEach { sut.onScroll(fixture.firstEvent, it, 10.0f, 0f) }
244+
sut.onUp(fixture.endEvent)
245+
246+
// Verify that the error message is logged only once during the entire gesture
247+
verify(logger, times(1))
248+
.log(SentryLevel.DEBUG, "Unable to find scroll target. No breadcrumb captured.")
249+
}
250+
232251
internal class ScrollableView : View(mock()), ScrollingView {
233252
override fun computeVerticalScrollOffset(): Int = 0
234253

sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/ViewHelpers.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ internal inline fun <reified T : View> mockView(
6767
return mockView
6868
}
6969

70-
internal fun Resources.mockForTarget(target: View, expectedResourceName: String) {
71-
whenever(getResourceEntryName(target.id)).thenReturn(expectedResourceName)
70+
internal fun Resources.mockForTarget(target: View, expectedResourceName: String?) {
71+
if (expectedResourceName == null) {
72+
whenever(getResourceEntryName(target.id))
73+
.thenThrow(Resources.NotFoundException("res not found"))
74+
} else {
75+
whenever(getResourceEntryName(target.id)).thenReturn(expectedResourceName)
76+
}
7277
}

0 commit comments

Comments
 (0)