Skip to content

fix(browser): Check for clock drift on page lifecycle events - #25091

Open
Lms24 wants to merge 1 commit into
lms/fix-replay-cls-timestampfrom
lms/feat-browser-page-lifecycle-drift-checks
Open

Lms24 wants to merge 1 commit into
lms/fix-replay-cls-timestampfrom
lms/feat-browser-page-lifecycle-drift-checks

Conversation

@Lms24

@Lms24 Lms24 commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #23054, from this review comment. Besides visibilitychange, we now also check for clock drift on freeze/resume (TIL) and pagehide/pageshow. This way the time origin is corrected right at the emissions, not at the next regular timestamp call.

freeze and resume only fire in Chromium. Other browsers never fire them, so the listeners do nothing there.

@Lms24
Lms24 added this pull request to stack #24904 October 6, 2026 09:58
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch from cee645a to d39c98a Compare October 6, 2026 10:01
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.76 kB +0.57% +166 B 🔺
@sentry/browser - with treeshaking flags 27.91 kB +0.57% +156 B 🔺
@sentry/browser - with treeshaking flags tracing without tracing 27.8 kB +0.55% +150 B 🔺
@sentry/browser (incl. Tracing) 51.8 kB +0.56% +286 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 51.81 kB +0.56% +286 B 🔺
@sentry/browser (incl. Tracing, Profiling) 54.78 kB +0.51% +276 B 🔺
@sentry/browser (incl. Tracing, Replay) 91.52 kB +0.32% +290 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.41 kB +0.29% +227 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 96.22 kB +0.31% +294 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 109.24 kB +0.32% +345 B 🔺
@sentry/browser (incl. Feedback) 47.28 kB +0.36% +166 B 🔺
@sentry/browser (incl. sendFeedback) 34.81 kB +0.47% +162 B 🔺
@sentry/browser (incl. FeedbackAsync) 39.9 kB +0.37% +146 B 🔺
@sentry/browser (incl. Metrics) 30.77 kB +0.53% +162 B 🔺
@sentry/browser (incl. Logs) 31.05 kB +0.55% +167 B 🔺
@sentry/browser (incl. Metrics & Logs) 31.72 kB +0.52% +164 B 🔺
@sentry/react 31.59 kB +0.51% +159 B 🔺
@sentry/react (incl. Tracing) 54.12 kB +0.53% +284 B 🔺
@sentry/vue 37.8 kB +0.68% +254 B 🔺
@sentry/vue (incl. Tracing) 54.73 kB +0.62% +335 B 🔺
@sentry/svelte 29.79 kB +0.55% +160 B 🔺
@sentry/remix (Remix 3 client bundle) 56.8 kB +0.45% +254 B 🔺
CDN Bundle 31.49 kB +0.52% +162 B 🔺
CDN Bundle (incl. Tracing) 52.3 kB +0.46% +237 B 🔺
CDN Bundle (incl. Logs, Metrics) 33.68 kB +0.36% +120 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 54.26 kB +0.43% +230 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 74.61 kB +0.31% +226 B 🔺
CDN Bundle (incl. Tracing, Replay) 89.97 kB +0.27% +235 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.93 kB +0.26% +232 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 96.12 kB +0.24% +224 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 98.12 kB +0.26% +247 B 🔺
CDN Bundle - uncompressed 92.9 kB +0.48% +437 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 155.44 kB +0.44% +666 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.43 kB +0.4% +396 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 161.39 kB +0.42% +666 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 229.49 kB +0.23% +509 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 275.62 kB +0.27% +728 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 281.56 kB +0.26% +728 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 289.32 kB +0.26% +728 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 295.25 kB +0.25% +728 B 🔺
@sentry/nextjs (client) 56.49 kB +0.54% +298 B 🔺
@sentry/sveltekit (client) 52.19 kB +0.55% +283 B 🔺
@sentry/core/server 40.85 kB +0.49% +198 B 🔺
@sentry/core/browser 13.71 kB +1.48% +199 B 🔺
@sentry/node 145.78 kB +0.15% +212 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.33 kB +0.14% +109 B 🔺
@sentry/node - without tracing 93.66 kB +0.22% +202 B 🔺
@sentry/node - without channel injection 123.92 kB +0.17% +200 B 🔺
@sentry/aws-serverless 101.88 kB +0.19% +192 B 🔺
@sentry/cloudflare (withSentry) - minified 209.67 kB +0.31% +638 B 🔺
@sentry/cloudflare (withSentry) 519.89 kB +0.41% +2.09 kB 🔺

View base workflow run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d39c98a. Configure here.

Comment thread packages/browser/src/client.ts
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch from d39c98a to 670fcc8 Compare October 6, 2026 10:12
@Lms24 Lms24 changed the title feat(browser): Check for clock drift on page lifecycle events fix(browser): Check for clock drift on page lifecycle events Oct 6, 2026
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch 2 times, most recently from c8aff48 to 91258cb Compare October 6, 2026 17:24
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch 2 times, most recently from e86377c to f166a90 Compare October 7, 2026 08:48
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch from f166a90 to e8cefdc Compare October 7, 2026 09:23
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch from e8cefdc to e57d8b4 Compare October 7, 2026 11:58
@Lms24
Lms24 marked this pull request as ready for review October 7, 2026 12:00
@Lms24
Lms24 requested a review from a team as a code owner October 7, 2026 12:00
@Lms24
Lms24 requested review from logaretm and msonnb and removed request for a team October 7, 2026 12:00
Also check on `freeze`/`resume` (Chromium only) and `pagehide`/`pageshow`
(back/forward cache). This makes the time origin correction happen at the
pause, not at the next regular timestamp call.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Lms24
Lms24 force-pushed the lms/feat-browser-page-lifecycle-drift-checks branch from e57d8b4 to c70799b Compare October 7, 2026 15:02
@Lms24 Lms24 self-assigned this Oct 7, 2026
Comment on lines 170 to 178
}

// Pages restored from the back/forward cache were paused while they were cached.
WINDOW.addEventListener?.('pagehide', () => timestampInSeconds());
WINDOW.addEventListener?.('pageshow', () => timestampInSeconds());

if (userInfo) {
this.on('beforeSendSession', addAutoIpAddressToSession);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: New event listeners for freeze, resume, pagehide, and pageshow are not cleaned up when a BrowserClient is destroyed, causing a memory leak.
Severity: MEDIUM

Suggested Fix

Implement a cleanup mechanism in the BrowserClient. The client should track the listeners it adds. A close() or dispose() method should be implemented or overridden to remove these event listeners from the global objects when the client is destroyed, preventing old client instances from being retained in memory.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/browser/src/client.ts#L170-L178

Potential issue: The `BrowserClient` adds global event listeners for `freeze`, `resume`,
`pagehide`, and `pageshow`. However, there is no corresponding cleanup logic to remove
these listeners when a client instance is no longer needed. If multiple `BrowserClient`
instances are created over an application's lifecycle, such as during hot-reloading, in
test suites, or by calling `Sentry.init()` multiple times, old client instances and
their closures will be retained in memory. This leads to a memory leak, as the new
listeners introduced in this change are not removed upon client destruction.

Did we get this right? 👍 / 👎 to inform future reviews.

@logaretm logaretm Oct 7, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: Should be easy to cleanup, no?

This branch has not been deployed

No deployments
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.

3 participants