Skip to content

Commit

Permalink
fix(v8/replay): Disable mousemove sampling in rrweb for iOS browsers (#…
Browse files Browse the repository at this point in the history
…14944)

backports #14937

ref #14534
  • Loading branch information
chargome authored Jan 10, 2025
1 parent fda1aee commit 0c3b2a4
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration'),
gzip: true,
limit: '75 KB',
limit: '76 KB',
},
{
name: '@sentry/browser (incl. Tracing, Replay) - with treeshaking flags',
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/utils-hoist/worldwide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type BackwardsCompatibleSentryCarrier = SentryCarrier & {

/** Internal global with common properties and Sentry extensions */
export type InternalGlobal = {
navigator?: { userAgent?: string };
navigator?: { userAgent?: string; maxTouchPoints?: number };
console: Console;
PerformanceObserver?: any;
Sentry?: any;
Expand Down
2 changes: 2 additions & 0 deletions packages/replay-internal/src/replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { createBreadcrumb } from './util/createBreadcrumb';
import { createPerformanceEntries } from './util/createPerformanceEntries';
import { createPerformanceSpans } from './util/createPerformanceSpans';
import { debounce } from './util/debounce';
import { getRecordingSamplingOptions } from './util/getRecordingSamplingOptions';
import { getHandleRecordingEmit } from './util/handleRecordingEmit';
import { isExpired } from './util/isExpired';
import { isSessionExpired } from './util/isSessionExpired';
Expand Down Expand Up @@ -394,6 +395,7 @@ export class ReplayContainer implements ReplayContainerInterface {
checkoutEveryNms: Math.max(360_000, this._options._experiments.continuousCheckout),
}),
emit: getHandleRecordingEmit(this),
...getRecordingSamplingOptions(),
onMutation: this._onMutationHandler,
...(canvasOptions
? {
Expand Down
25 changes: 25 additions & 0 deletions packages/replay-internal/src/util/getRecordingSamplingOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { GLOBAL_OBJ } from '@sentry/core';

const NAVIGATOR = GLOBAL_OBJ.navigator;

/**
* Disable sampling mousemove events on iOS browsers as this can cause blocking the main thread
* https://github.com/getsentry/sentry-javascript/issues/14534
*/
export function getRecordingSamplingOptions(): Partial<{ sampling: { mousemove: boolean } }> {
if (
/iPhone|iPad|iPod/i.test((NAVIGATOR && NAVIGATOR.userAgent) || '') ||
(/Macintosh/i.test((NAVIGATOR && NAVIGATOR.userAgent) || '') &&
NAVIGATOR &&
NAVIGATOR.maxTouchPoints &&
NAVIGATOR.maxTouchPoints > 1)
) {
return {
sampling: {
mousemove: false,
},
};
}

return {};
}
54 changes: 54 additions & 0 deletions packages/replay-internal/test/integration/rrweb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,58 @@ describe('Integration | rrweb', () => {
}
`);
});

it('calls rrweb.record with updated sampling options on iOS', async () => {
// Mock iOS user agent
const originalNavigator = global.navigator;
Object.defineProperty(global, 'navigator', {
value: {
userAgent:
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
},
configurable: true,
});

const { mockRecord } = await resetSdkMock({
replayOptions: {},
sentryOptions: {
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 1.0,
},
});

// Restore original navigator
Object.defineProperty(global, 'navigator', {
value: originalNavigator,
configurable: true,
});

expect(mockRecord.mock.calls[0]?.[0]).toMatchInlineSnapshot(`
{
"blockSelector": ".sentry-block,[data-sentry-block],base,iframe[srcdoc]:not([src]),img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]",
"collectFonts": true,
"emit": [Function],
"errorHandler": [Function],
"ignoreSelector": ".sentry-ignore,[data-sentry-ignore],input[type="file"]",
"inlineImages": false,
"inlineStylesheet": true,
"maskAllInputs": true,
"maskAllText": true,
"maskAttributeFn": [Function],
"maskInputFn": undefined,
"maskInputOptions": {
"password": true,
},
"maskTextFn": undefined,
"maskTextSelector": ".sentry-mask,[data-sentry-mask]",
"onMutation": [Function],
"sampling": {
"mousemove": false,
},
"slimDOMOptions": "all",
"unblockSelector": "",
"unmaskTextSelector": "",
}
`);
});
});

0 comments on commit 0c3b2a4

Please sign in to comment.