Repository navigation
Description
The project plan holds back every clock change that alters serialized timing or the public API until v9. No other open issue in this project tracks those changes. This one does.
Each item below is breaking. It either changes a critical customer metric or breaks the public API.
1. Span timing on one AnchoredClock per transaction
Today each span reads the wall clock for its own start (Span calls options.getDateProvider().now()). Its end is that start plus a System.nanoTime() difference. So the starts of two spans are two separate wall-clock readings. If the wall clock steps between them, a child span can start before its parent.
The fix is the design that #6045 shipped as API only. Create one AnchoredClock per transaction in SentryTracer, and project every span timestamp from it. Nothing calls AnchoredClock yet.
Why it's breaking:
- Durations start counting deep sleep on Android. The ticker there is
CLOCK_BOOTTIME.System.nanoTime()isCLOCK_MONOTONIC, which stops in deep sleep. Any span or transaction that crosses a deep sleep gets longer. This matches iOS, which is a project goal, but it changes span and transaction durations customers chart and alert on. - Child span
start_timestamps move by less than a millisecond. Root spans don't change.
2. Decide whether app start follows
TimeSpan runs on SystemClock.uptimeMillis(), which also stops in deep sleep. It drives the app start, process init, Application.onCreate, content provider and activity lifecycle spans.
Open question: should app start count deep sleep too? #5752 argued that launches with a Doze in the middle don't reflect what users actually experience. If app start does switch, it's breaking twice:
- Metric: a launch where the device sleeps before the first frame would include the sleep instead of leaving it out, so app-start p95/p99 go up. Incorrect app start transaction duration when app goes in sleep #5752 only drops launches where the deadline fires late, not this case.
- API:
TimeSpanis insentry-android-core.api. Its methods are named for uptime (setStartedAt(uptimeMs),getStartUptimeMs()), andInternalSentrySdkserializes it for the hybrid SDKs.
#6104's AndroidEnvelopeCache call site doesn't depend on this decision. It can take its own boottime reading at SDK init.
3. Remove ICurrentDateProvider
ICurrentDateProviderandCurrentDateProviderare@ApiStatus.Internalbut listed insentry.api. Neither is deprecated yet.- The public
ReplayIntegrationconstructors take anICurrentDateProvider. The sentry-dart Android plugin calls the four-argument constructor withCurrentDateProvider.getInstance(), so removing it breaks Flutter. Coordinate the change with sentry-dart. AndroidCurrentDateProvideris internal and not in the.apifile (deprecated by Deprecate AndroidCurrentDateProvider in favor of MonotonicTicker #6102). Delete it once Clean up the remaining AndroidCurrentDateProvider usages #6104 has moved its callers.- Session Replay drives interval/window math from the wall clock #5578 covers moving Replay's capture strategies off
ICurrentDateProvider.
Done when
- Spans and transactions take their timestamps from one
AnchoredClockper transaction. - The app-start decision is made, and either implemented or explicitly deferred.
ICurrentDateProvideris gone fromsentry.api, and sentry-dart has been updated.- The v9 changelog lists each change.
Agent notes
Verified on main at 1b8668ae2b (2026-11-06).
- Span start:
sentry/src/main/java/io/sentry/Span.java:68,:86. Span end:SentryNanotimeDate.laterDateNanosTimestampByDiff, serialized inprotocol/SentrySpan.java:73-75andprotocol/SentryTransaction.java:62-68. - Android date provider:
SentryAndroidDateProvider→SentryNanotimeDate(System.currentTimeMillis()+System.nanoTime()). - Ticker:
AndroidMonotonicTicker.tickNanos()=SystemClock.elapsedRealtimeNanos(). Epoch:SentryOptions.getEpochClock(). AnchoredClocklives insentry/src/main/java/io/sentry/time/AnchoredClock.java. Nothing outsideio.sentry.timeuses it.- Constraint for item 1:
Choreographerframe timestamps are onCLOCK_MONOTONIC.SpanFrameMetricsCollectorhas to convert between the two clocks instead of subtracting across them. TimeSpan:sentry-android-core/src/main/java/io/sentry/android/core/performance/TimeSpan.java. Serialized for hybrid SDKs inInternalSentrySdk.java:366-370.- sentry-dart caller:
packages/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt, around line 293. - Replay
TODO [v9]markers:BaseCaptureStrategy.kt:59,ReplayGestureConverter.kt:16.
Activity
linear-code commentedon Nov 6, 2026
JAVA-827