fix(core): Use wall clock for structured log timestamps#22585
Conversation
Structured logs stamped their timestamp via `timestampInSeconds()`, which returns `performance.timeOrigin + performance.now()` with no wall-clock sanity check. On platforms where the Performance API is not anchored to the UNIX epoch (notably React Native/Hermes, where it tracks device uptime), this made log timestamps off by a large, constant offset while error events (which use `Date.now()`) stayed correct. Switch the log path to `dateTimestampInSeconds()` so log timestamps use the wall clock and match error-event timestamps on every platform. Sub-second ordering is preserved via the existing `sentry.timestamp.sequence` attribute. Scope is limited to the log path; `timestampInSeconds()` and its other consumers (spans, sessions, breadcrumbs, metrics) are unchanged. Closes getsentry/sentry-react-native#6510 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3aea457. Configure here.
| // by a large, constant offset. Using the wall clock keeps log timestamps consistent with error-event timestamps | ||
| // (which also use `dateTimestampInSeconds()`). Sub-second ordering is preserved via the `sentry.timestamp.sequence` | ||
| // attribute below. See: https://github.com/getsentry/sentry-react-native/issues/6510 | ||
| const timestamp = dateTimestampInSeconds(); |
There was a problem hiding this comment.
Shared sequence breaks across clocks
Medium Severity
Logs now call dateTimestampInSeconds() while metrics still call timestampInSeconds(), but both share one getSequenceAttribute counter keyed by millisecond. On divergent clocks (the React Native/Hermes case this fixes), an interleaved metric resets that counter, so same-ms logs can both get sentry.timestamp.sequence 0 and lose tie-break ordering.
Reviewed by Cursor Bugbot for commit 3aea457. Configure here.
There was a problem hiding this comment.
This is valid but I'd wait for feedback from the team before expanding the scope of this change


Before submitting a pull request, please take a look at our
Contributing guidelines and verify:
yarn lint) & (yarn test).Closes getsentry/sentry-react-native#6510
Structured logs (
Sentry.logger.*) are stamped with a timestamp that can be wrong by a large, constant offset on platforms where the Performance API is not anchored to the UNIX epoch — notably React Native/Hermes, whereperformance.timeOrigin + performance.now()tracks device uptime rather than wall-clock time. In one report the offset was ~4.25 days, while error events (which useDate.now()) were correct.Log timestamps are produced by
timestampInSeconds(), which returnsperformance.timeOrigin + performance.now()without any wall-clock sanity check. This PR switches the log path todateTimestampInSeconds()(i.e.Date.now()), so log timestamps use the wall clock and match error-event timestamps on every platform.Sub-second ordering is unaffected: logs already carry the
sentry.timestamp.sequenceattribute, which is the mechanism used to break ties when two logs share the same timestamp.Scope: this is intentionally limited to the log path only.
timestampInSeconds()and all of its other consumers (spans, sessions, breadcrumbs, metrics) are left unchanged, so tracing behavior is not affected.Background
The regression was introduced in #16133 (
ref(core): Switch to standardized log envelope), first shipped in@sentry/core@9.16.0. Before that change, logs were stamped withnew Date().getTime()(wall clock); the refactor switched them totimestampInSeconds().Related: #2590 (Performance-clock vs wall-clock skew).
How was it tested?
_INTERNAL_captureLogstamps logs withdateTimestampInSeconds()(wall clock) and does not calltimestampInSeconds().sentry.timestamp.sequencetests, which mockedtimestampInSeconds(), to mockdateTimestampInSeconds()accordingly.packages/corelogs test suites pass (104 tests).