Repository navigation
Description
Split from #6522. These two pieces measure how long something took, so they can move to a Stopwatch before v9. Check-in durations did the same in #6032. The gesture timestamps (when something happened) stay on the wall clock and are part of #6522, which waits for v9.
What reads the wall clock
While a finger moves, ReplayGestureConverter batches touch positions and sends them as one move event every 500ms. Two things there subtract one wall-clock reading from another:
- Batch timer. The batch is sent once
now - touchMoveBaselinepasses 500ms. This only decides when to send, so nothing in the payload changes. It's the sibling of the 50ms move debounce that fix(replay): Measure recording deadlines on a monotonic clock (JAVA-575) #6090 moved to aDeadline. timeOffset. Each position records how long after the batch started it happened, always under about 500ms. It is sent to Sentry, but it's a duration, not a timestamp.
What goes wrong
If the clock steps backward during a swipe, now - touchMoveBaseline goes negative. The batch isn't sent until the clock catches back up, and if the finger lifts first, the batched positions are dropped. A forward step sends the batch at once, with offsets stretched by the size of the step.
Not a breaking change
With no clock step, the values are the same as today. It doesn't touch session counts, the public API or a critical customer metric.
Done when
- The batch timer and
timeOffsetcome from oneStopwatch, started when a batch begins, on thetickerthe converter already takes. - Event timestamps (touch start, end and cancel, and the move event's
timestamp) still usedateProvider. Those move in Session Replay segment, buffer and gesture timestamps read the wall clock #6522. - Tests cover a backward and a forward clock step during a swipe.
Agent notes
Verified on main at 5652060246 (2026-11-09).
ReplayGestureConverter.kt::39(now),:54-55(baseline set,0Lsentinel),:63(timeOffset),:67-68(batch check againstCAPTURE_MOVE_EVENT_THRESHOLD= 500),:76(pos.timeOffset -= totalOffset),:84(baseline reset). A nullableStopwatchcan replace the0Lsentinel.- Leave alone (Session Replay segment, buffer and gesture timestamps read the wall clock #6522):
:74(move eventtimestamp),:105,:128,:142(touch timestamps). - The
tickerconstructor parameter came in with fix(replay): Measure recording deadlines on a monotonic clock (JAVA-575) #6090 and drives the 50ms debounce at:43. - Keep the
TODO [v9]at:16.dateProvideris still needed for the event timestamps. Stopwatch(sentry/src/main/java/io/sentry/time/Stopwatch.java):started(MonotonicTicker),elapsed(TimeUnit),elapsedNanos().- Test gotcha from fix(replay): Measure recording deadlines on a monotonic clock (JAVA-575) #6090: in gesture tests, a clock step over ~500ms crosses
CAPTURE_MOVE_EVENT_THRESHOLD. Keep steps small when testing the debounce. - Precedent for serialized durations on a monotonic clock: check-ins, fix: use System.nanoTime() for cron check-in duration measurement #5611 (
System.nanoTime()) then ref(checkin): Measure check-in durations with Stopwatch (JAVA-576) #6032 (Stopwatch).
Activity
linear-code commentedon Nov 9, 2026
JAVA-830
github-actions commentedon Nov 11, 2026
A PR closing this issue has just been released 🚀
This issue was referenced by PR #6538, which was included in the 8.64.0 release.