Skip to content

Commit 25c62a4

Browse files
authored
Merge db94d96 into 2bfacef
2 parents 2bfacef + db94d96 commit 25c62a4

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
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: 47 additions & 0 deletions
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
@@ -229,6 +232,50 @@ 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 mockLogger = mock<ILogger>()
238+
fixture.options.setLogger(mockLogger)
239+
240+
// Create a setup where no scrollable view is found
241+
// Use regular View which doesn't implement ScrollingView/AbsListView/ScrollView
242+
fixture.target =
243+
mockView<View>(
244+
event = fixture.firstEvent,
245+
touchWithinBounds = true,
246+
context = fixture.context,
247+
)
248+
fixture.window.mockDecorView<ViewGroup>(event = fixture.firstEvent) {
249+
whenever(it.childCount).thenReturn(1)
250+
whenever(it.getChildAt(0)).thenReturn(fixture.target)
251+
}
252+
253+
fixture.resources.mockForTarget(fixture.target, "test_view")
254+
whenever(fixture.context.resources).thenReturn(fixture.resources)
255+
whenever(fixture.target.context).thenReturn(fixture.context)
256+
whenever(fixture.activity.window).thenReturn(fixture.window)
257+
doAnswer { (it.arguments[0] as ScopeCallback).run(fixture.scope) }
258+
.whenever(fixture.scopes)
259+
.configureScope(any())
260+
doAnswer {
261+
(it.arguments[0] as Scope.IWithPropagationContext).accept(fixture.propagationContext)
262+
fixture.propagationContext
263+
}
264+
.whenever(fixture.scope)
265+
.withPropagationContext(any())
266+
267+
val sut = SentryGestureListener(fixture.activity, fixture.scopes, fixture.options)
268+
269+
sut.onDown(fixture.firstEvent)
270+
// Multiple onScroll calls during the same gesture - should only log once
271+
fixture.eventsInBetween.forEach { sut.onScroll(fixture.firstEvent, it, 10f, 0f) }
272+
sut.onUp(fixture.endEvent)
273+
274+
// Verify that the error message is logged only once during the entire gesture
275+
verify(mockLogger, times(1))
276+
.log(SentryLevel.DEBUG, "Unable to find scroll target. No breadcrumb captured.")
277+
}
278+
232279
internal class ScrollableView : View(mock()), ScrollingView {
233280
override fun computeVerticalScrollOffset(): Int = 0
234281

0 commit comments

Comments
 (0)