Conversation
size-limit report 📦
|
|
The two-origin divergence Bugbot flagged is real: Fixed in #23067, stacked on top of this PR, which exposes the corrected origin and switches over the consumers where the divergence persists (INP, replay, and profiling's Keeping it out of this PR so each change stays independently reviewable — this one is limited to how |
|
Confirmed on a real iPhone running React Native 0.86 with One structured log embedded its emission wall time in the message body:
The full structured-log stream was present under the older window with the same displacement, while error events remained wall-clock-correct. This matches the React Native Apple clock change in react-native#55977 and the symptom reported in getsentry/sentry-react-native#6510. We applied the same per-call re-anchoring shape downstream as a version-pinned patch. Package-level regression tests against the real One potentially useful addition to this PR's test suite: the current sleep test starts with an aligned first call and then accumulates drift. Our device also exercised the other entry condition, where |
|
This pull request has gone three weeks without activity. In another week, I will close it. But! If you comment or otherwise update it, I will reset the clock, and if you apply the label |
|
Getting the same issue, has this been closed permanently? |
|
@plgrazon no, this is still WIP but the change is non-trivial. I'm currently completely booked on the new JS major but I hope to get some time to pick this up next week again. |
|
@Lms24 no worries. thank you! |
…red with `timestampInSeconds` re-derives its time origin when it detects clock drift, so a single origin is only valid for part of a page's lifetime. Consumers that convert a `PerformanceEntry`'s monotonic `startTime` to wall clock time have no way to know which one applied to a given entry, and `browserPerformanceTimeOrigin` caches the origin resolved at SDK init and never revisits it. Adds `performanceTimeToSeconds`, which keeps the superseded origins around and picks the one that was in effect when the passed time was measured. Entries reported long after the fact — INP on pagehide, replay entries buffered until flush — therefore stay on the timeline they were recorded on instead of being retroactively shifted by a drift that happened afterwards. The correction boundary is the `performance.now()` value the drift was detected at, which is an upper bound on where it actually happened; that is as close as it can be pinned down without a second clock. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… own time origin Routes the consumers that convert a monotonic `PerformanceEntry` time long after the entry was recorded through `performanceTimeToSeconds`, so a clock drift correction no longer shifts entries that were timed correctly: - INP and CLS report on pagehide, potentially hours after the interaction or layout shift they describe. LCP keeps the cached origin: it starts *at* the origin by construction, so moving it would detach it from its pageload parent. - Replay buffers raw entries and only converts them on flush, which for a long-running session can be minutes later. - Continuous profiling samples are `performance.timeOrigin`-relative like any other monotonic time. Also drops `adjustForOriginChange` from `convertJSSelfProfileToSampledFormat`. `elapsed_since_start_ns` is a difference between two raw monotonic values, so no origin belongs in it at all - the profile is anchored to the wall clock by the enclosing payload's `timestamp`. The term was harmless only because it evaluated to ~0 whenever the SDK origin matched `performance.timeOrigin`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
456dd81 to
ded4f36
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1a9120e. Configure here.
…igin `browserPerformanceTimeOrigin` was cached at init, so after a drift correction resource, long task, long animation frame, click and user timing spans landed a whole sleep before the navigation they belong to, and most were dropped by the "started before the navigation" checks. It now takes the monotonic time being converted and returns the origin in effect then, defaulting to the page load. Also: - Soft navigation LCP resolves against the origin at the navigation start. - A correction now applies from the previous check on, so the interaction that wakes the SDK up after a sleep lands on the corrected timeline. - The page load origin survives the segment cap. - Without `performance.timeOrigin`, monotonic times convert against `Date.now() - performance.now()` again instead of producing `NaN`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A drift correction applies from the last check at which both clocks agreed, so entries recorded between that check and the device going to sleep land on the wrong side of it. Devices usually hide the page before sleeping and show it again on wake, so checking the clocks on `visibilitychange` pins the correction to the sleep itself rather than to whenever the SDK next takes a timestamp. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
At 5 minutes, any sleep shorter than that left spans, logs and metrics behind the wall clock (and errors) for the rest of the page's life. 15 seconds is still far above `Date.now()` jitter and typical NTP adjustments, so it only catches real drift. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

timestampInSecondscombinesperformance.timeOriginwithperformance.now(), and on some platformsperformance.now()stops while the device sleeps. After a sleep, spans, logs and metrics therefore end up behind the wall clock (errors and breadcrumbs useDate.now(), so they don't). This PR now checks both clocks on every call and re-derives the origin once they differ by more than 5 minutes. Elapsed time still comes fromperformance.now(), so it keeps sub-millisecond precision.The correction only applies going forward. Performance entries are often converted long after they happen (INP and CLS on pagehide, replay entries on flush), so the SDK keeps the old origins and
performanceTimeToSeconds()converts each monotonic time against the origin in effect when it was measured. Web vitals, replay and continuous profiling now use it.Fixes #2590
Supersedes #22488, #22585, #23067, #23068
🤖 Generated with Claude Code