Skip to content

docs(time): Steer new measurements at the io.sentry.time clock APIs - #6088

Draft
runningcode wants to merge 1 commit into
mainfrom
no/docs-clock-apis
Draft

docs(time): Steer new measurements at the io.sentry.time clock APIs#6088
runningcode wants to merge 1 commit into
mainfrom
no/docs-clock-apis

Conversation

@runningcode

Copy link
Copy Markdown
Contributor

📜 Description

Documentation only — no behavior change.

1. On the singleton clocks. JavaMonotonicTicker, SystemEpochClock and AndroidMonotonicTicker each expose a getInstance(). Each one now carries a Javadoc note on that method pointing callers at SentryOptions#getMonotonicTicker() / SentryOptions#getEpochClock() instead, so they resolve the per-platform implementation rather than pinning themselves to one, and says which callers legitimately still call getInstance() directly (the SentryOptions / SentryAndroidOptions accessors that supply the default, and tests that mean a specific implementation).

2. In AGENTS.md. A new "Measuring Time" section under Development Guidelines tells agents that new code reading a clock uses io.sentry.time, and not DateUtils.getCurrentDateTime(), System.currentTimeMillis(), System.nanoTime(), SystemClock or any SentryDateProvider implementation. It maps the intent of the measurement onto the type that enforces it (EpochClock/Timestamp, Stopwatch, Deadline, AnchoredClock, MonotonicTicker), repeats the "get it from the options object" rule, and asks that adding a new abstraction be a deliberate step — re-read the existing types first, then name the invariant the new one exists to enforce and propose it — rather than a way around an awkward call site or an excuse to inline raw tick arithmetic.

💡 Motivation and Context

The io.sentry.time package landed over #6028, #6045 and #6030. Nothing so far records how it is meant to be used, and the two ways to get it wrong are both easy and quiet:

  • JavaMonotonicTicker.getInstance() compiles and works on Android, but it is System.nanoTime(), which stops counting while the device is suspended. Any interval measured across a deep sleep silently comes out short. SentryAndroidOptions overrides the accessor with a CLOCK_BOOTTIME-backed ticker precisely to avoid that, and reading the accessor is the only thing that picks it up.
  • The pre-io.sentry.time clock reads are still all over the repository, so the nearest example an agent finds is usually the one it should not copy.

💚 How did you test it?

No tests — comments and a Markdown file. Verified ./gradlew spotlessApply apiDump is a no-op beyond the edits (no .api changes), and that :sentry:javadoc and :sentry-android-core:javaDocReleaseGeneration both build clean, which confirms the new {@link} targets resolve.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes. — n/a, documentation only
  • 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. — no API change; all three classes are @ApiStatus.Internal

🔮 Next steps

The AGENTS.md section is deliberately about new code only. Migrating the existing SentryDateProvider and raw System.nanoTime() call sites is the remaining work in the clock series and stays out of this PR.

#skip-changelog

Document on each singleton clock's getInstance() that callers should read
the ticker or wall clock off the options object instead, so they get the
per-platform implementation rather than pinning themselves to one. Calling
JavaMonotonicTicker.getInstance() on Android is the trap worth naming: it
stops counting through a device suspend, so intervals spanning a deep sleep
come out short.

Add an AGENTS.md section so new measurement code reaches for io.sentry.time
rather than DateUtils.getCurrentDateTime() or a SentryDateProvider, picks the
abstraction by what the number is for, and treats adding a new abstraction as
a deliberate step rather than a way around an awkward call site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sentry

sentry Bot commented Sep 10, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

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