Skip to content

Commit d5a0c04

Browse files
Fix(Replay): dont record ignored/dropped errors (#5885)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent a688ab9 commit d5a0c04

3 files changed

Lines changed: 289 additions & 114 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
### Fixes
1212

13+
- Session replay will no longer start recording when an event was ignored or dropped. ([#5885](https://github.com/getsentry/sentry-react-native/pull/5885))
1314
- Capture native exceptions consumed by Expo's bridgeless error handling on Android ([#5871](https://github.com/getsentry/sentry-react-native/pull/5871))
1415
- Fix SIGABRT crash on launch when `mobileReplayIntegration` is not configured and iOS deployment target >= 16.0 ([#5858](https://github.com/getsentry/sentry-react-native/pull/5858))
1516
- Reduce `reactNavigationIntegration` performance overhead ([#5840](https://github.com/getsentry/sentry-react-native/pull/5840), [#5842](https://github.com/getsentry/sentry-react-native/pull/5842), [#5849](https://github.com/getsentry/sentry-react-native/pull/5849))

packages/core/src/js/replay/mobilereplay.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Client, DynamicSamplingContext, Event, EventHint, Integration, Metric } from '@sentry/core';
1+
import type { Client, DynamicSamplingContext, ErrorEvent, Event, EventHint, Integration, Metric } from '@sentry/core';
22
import { debug } from '@sentry/core';
33
import { isHardCrash } from '../misc';
44
import { hasHooks } from '../utils/clientutils';
@@ -213,7 +213,7 @@ export const mobileReplayIntegration = (initOptions: MobileReplayOptions = defau
213213
return nativeReplayId;
214214
}
215215

216-
async function processEvent(event: Event, hint: EventHint): Promise<Event> {
216+
async function processEvent(event: ErrorEvent, hint: EventHint): Promise<ErrorEvent> {
217217
const hasException = event.exception?.values && event.exception.values.length > 0;
218218
if (!hasException) {
219219
// Event is not an error, will not capture replay
@@ -303,6 +303,26 @@ export const mobileReplayIntegration = (initOptions: MobileReplayOptions = defau
303303
});
304304

305305
client.on('beforeAddBreadcrumb', enrichXhrBreadcrumbsForMobileReplay);
306+
307+
// Wrap beforeSend to run processEvent after user's beforeSend
308+
const clientOptions = client.getOptions();
309+
const originalBeforeSend = clientOptions.beforeSend;
310+
clientOptions.beforeSend = async (event: ErrorEvent, hint: EventHint): Promise<ErrorEvent | null> => {
311+
let result: ErrorEvent | null = event;
312+
if (originalBeforeSend) {
313+
result = await originalBeforeSend(event, hint);
314+
if (result === null) {
315+
// Event was dropped by user's beforeSend, don't capture replay
316+
return null;
317+
}
318+
}
319+
try {
320+
return await processEvent(result, hint);
321+
} catch (error) {
322+
debug.error(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} Failed to process event for replay`, error);
323+
return result;
324+
}
325+
};
306326
}
307327

308328
function getReplayId(): string | null {
@@ -314,7 +334,6 @@ export const mobileReplayIntegration = (initOptions: MobileReplayOptions = defau
314334
return {
315335
name: MOBILE_REPLAY_INTEGRATION_NAME,
316336
setup,
317-
processEvent,
318337
options: options,
319338
getReplayId: getReplayId,
320339
};

0 commit comments

Comments
 (0)