Skip to content

ref(time): Deprecate the legacy date and clock providers (JAVA-571) - #6043

Draft
runningcode wants to merge 4 commits into
no/java-579-anr-uptime-clockfrom
no/java-571-deprecate-date-providers
Draft

ref(time): Deprecate the legacy date and clock providers (JAVA-571)#6043
runningcode wants to merge 4 commits into
no/java-579-anr-uptime-clockfrom
no/java-571-deprecate-date-providers

Conversation

@runningcode

@runningcode runningcode commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

PR Stack (Clock semantics hardening)


📜 Description

Marks the legacy date and clock surface as deprecated, now that the internal consumers that could
move have moved (#6029, #6030, #6032, #6041). Nothing is migrated here and nothing is removed — the
point is to start the warning cycle before the next major, so users and the 9.x.x branch get a
full release of notice.

Deprecated Replacement
ICurrentDateProvider.getCurrentTimeMillis() MonotonicClock for an interval, SentryDateProvider for a timestamp
CurrentDateProvider.getInstance() SentryDateProvider for a timestamp, MonotonicClock for an interval
AndroidCurrentDateProvider.getInstance() MonotonicClock (this one was SystemClock.uptimeMillis() all along)
DateUtils.getCurrentDateTime() options.getDateProvider().now()
AndroidDateUtils.getCurrentSentryDateTime() options.getDateProvider()

The DateUtils class is deliberately not deprecated: only getCurrentDateTime() reads a clock,
while its other fourteen statics are pure conversion and formatting helpers used all over the SDK.

Two deviations from the plan, both forced

1. The annotations sit on members, not on the types. The plan called for deprecating
ICurrentDateProvider, CurrentDateProvider and AndroidCurrentDateProvider as types. That cannot
compile here: the Android modules build at Java 8, where javac still emits a deprecation warning for
an import of a deprecated type (JEP 211 elides those only from source 9 on), -Xlint:all -Werror
turns it into an error, and an import declaration cannot carry a @SuppressWarnings — a class-level
suppression does not cover it either. I verified both halves of that empirically. Thirteen Java files
in sentry-android-core import these types; the alternative was writing
io.sentry.transport.ICurrentDateProvider inline at ~40 use sites until the next major.

Deprecating getCurrentTimeMillis() and getInstance() warns any caller just as loudly, and every
warning it produces lands somewhere a suppression can go. The type-level javadoc still names the
replacement, so IDEs and Javadoc readers see it.

2. Kotlin call sites are left warning, not suppressed. -Werror applies to JavaCompile only,
so the 17 warnings in sentry-android-replay and sentry-okhttp do not break anything. They are the
live migration list for JAVA-575; suppressing them would trade a checklist for a comment. That module
already carries other deprecation warnings, so this is not a new kind of noise. Say the word if you'd
rather have them suppressed.

💡 Motivation and Context

ICurrentDateProvider is the defect JAVA-571 was filed about. One interface carried two
incompatible clocks — CurrentDateProvider is System.currentTimeMillis(), AndroidCurrentDateProvider
is SystemClock.uptimeMillis() — and nothing in the name or the type said which. A field declared
ICurrentDateProvider accepts either, and the two disagree by however long the device has been
suspended.

Each of the 21 Java suppressions carries a // TODO [MAJOR] naming the replacement that site should
take, because a suppressed warning stops being a checklist entry. Nearly all of them are frozen until
the next major because they produce serialized timestamps — SentryEvent, Breadcrumb, Session,
SentryReplayEvent, ProfilingTraceData, both profilers, the activity-lifecycle span helpers. Only
ClientReportRecorder and EnvelopeCache are internal. That is expected: this PR marks the surface,
it does not migrate it.

Four sites must stay on the wall clock and say so: AnrV2Integration, TombstoneIntegration and
ApplicationExitInfoHistoryDispatcher compare against epoch ApplicationExitInfo timestamps, and
LifecycleWatcher against Session.getStarted().

  • resolves: JAVA-571

💚 How did you test it?

No behaviour changes, so no new tests — this is annotations plus suppressions.

./gradlew :sentry:test :sentry:apiCheck :sentry-android-core:testReleaseUnitTest :sentry-android-core:apiCheck :sentry-android-replay:testReleaseUnitTest :sentry-okhttp:test :sentry-apache-http-client-5:test — green.

./gradlew spotlessApply apiDump produces no .api diff: BCV does not record annotations.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

The removals, and the serialized-value migrations behind every // TODO [MAJOR] here, belong to the
9.x.x branch: JAVA-572 (span durations), JAVA-575 (replay timings), JAVA-577 (session durations),
JAVA-578 (profiler re-anchoring), JAVA-642 (app-start spans).

⚠️ Merge this PR using a merge commit (not squash), so the rest of the stack keeps a clean history.

@linear-code

linear-code Bot commented Sep 2, 2026

Copy link
Copy Markdown

JAVA-571

@sentry

sentry Bot commented Sep 2, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.55.0 (1) release

⚙️ sentry-android Build Distribution Settings

@runningcode
runningcode force-pushed the no/java-579-anr-uptime-clock branch from cabb812 to 77eb8c9 Compare September 2, 2026 13:35
@runningcode
runningcode force-pushed the no/java-571-deprecate-date-providers branch 2 times, most recently from 4f8f1ff to d35ab7c Compare September 2, 2026 13:37
@runningcode
runningcode force-pushed the no/java-579-anr-uptime-clock branch from 77eb8c9 to 2065803 Compare September 2, 2026 13:37
@runningcode
runningcode force-pushed the no/java-579-anr-uptime-clock branch from 2065803 to 498932f Compare September 3, 2026 15:11
@runningcode
runningcode force-pushed the no/java-571-deprecate-date-providers branch from d35ab7c to f375021 Compare September 3, 2026 15:11
It reads the wall clock into a java.util.Date at millisecond resolution.
SentryDateProvider already owns wall time, is configurable, stubbable in
tests and resolves finer, so there is no reason for new code to reach for
the static.

The class itself is not deprecated: its other fourteen statics are pure
conversion and formatting helpers with no clock in them.

Every caller keeps working and gets a suppression, because -Xlint:all
-Werror turns the warning into a build failure. Each suppression carries a
TODO [MAJOR] naming the replacement, since a suppressed warning is no
longer a checklist entry — and nearly all of these callers are frozen
until the next major anyway, as they stamp serialized timestamps.
One interface carried two incompatible clocks: CurrentDateProvider is
System.currentTimeMillis() and AndroidCurrentDateProvider is
SystemClock.uptimeMillis(). Nothing in the name or the type said which,
which is the defect JAVA-571 is about — a field declared
ICurrentDateProvider accepts either, and the two disagree by however long
the device has been suspended. MonotonicClock names the guarantee it
gives, and SentryDateProvider covers wall time.

The annotation goes on the members rather than the types: the Android
modules compile at Java 8, where javac still warns on imports of a
deprecated type, and an import declaration cannot carry a
@SuppressWarnings. Deprecating getCurrentTimeMillis() and getInstance()
warns any caller just the same, and every warning it produces lands
somewhere that can be suppressed.

Each suppression names the replacement the site should take at the next
major. Several of these must stay on the wall clock: AnrV2Integration,
TombstoneIntegration and ApplicationExitInfoHistoryDispatcher compare
against epoch ApplicationExitInfo timestamps, and LifecycleWatcher against
Session.getStarted().
…VA-571)

Its own javadoc already told callers to prefer options.getDateProvider();
this makes the compiler say so. The static holder cannot be configured or
stubbed, which is the whole reason the note was there.

Annotated on the method rather than the class, for the same import reason
as the current-date providers.
@runningcode
runningcode force-pushed the no/java-579-anr-uptime-clock branch from 498932f to ae9d046 Compare September 3, 2026 15:41
@runningcode
runningcode force-pushed the no/java-571-deprecate-date-providers branch from f375021 to 86b6e5e Compare September 3, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant