Skip to content

Commit d81ff9f

Browse files
committed
feat(replay): Allow to opt-in to capture replay exceptions
You can define `_experiments: { captureExceptions: true }`.
1 parent 5de6e43 commit d81ff9f

File tree

4 files changed

+27
-37
lines changed

4 files changed

+27
-37
lines changed

packages/replay/src/integration.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Integration } from '@sentry/types';
55
import { DEFAULT_ERROR_SAMPLE_RATE, DEFAULT_SESSION_SAMPLE_RATE } from './constants';
66
import { ReplayContainer } from './replay';
77
import type { RecordingOptions, ReplayConfiguration, ReplayPluginOptions } from './types';
8-
import { captureInternalException } from './util/captureInternalException';
98
import { isBrowser } from './util/isBrowser';
109

1110
const MEDIA_SELECTORS = 'img,image,svg,path,rect,area,video,object,picture,embed,map,audio';
@@ -118,9 +117,7 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
118117
}
119118

120119
if (isBrowser() && this._isInitialized) {
121-
const error = new Error('Multiple Sentry Session Replay instances are not supported');
122-
captureInternalException(error);
123-
throw error;
120+
throw new Error('Multiple Sentry Session Replay instances are not supported');
124121
}
125122

126123
this._isInitialized = true;

packages/replay/src/replay.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable max-lines */ // TODO: We might want to split this file up
2-
import { addGlobalEventProcessor, getCurrentHub, Scope, setContext } from '@sentry/core';
2+
import { addGlobalEventProcessor, captureException, getCurrentHub, Scope, setContext } from '@sentry/core';
33
import { Breadcrumb, Client, DataCategory, Event, EventDropReason } from '@sentry/types';
44
import { addInstrumentationHandler, createEnvelope, logger } from '@sentry/utils';
55
import debounce from 'lodash.debounce';
@@ -33,7 +33,6 @@ import type {
3333
SendReplay,
3434
} from './types';
3535
import { addInternalBreadcrumb } from './util/addInternalBreadcrumb';
36-
import { captureInternalException } from './util/captureInternalException';
3736
import { createBreadcrumb } from './util/createBreadcrumb';
3837
import { createPayload } from './util/createPayload';
3938
import { dedupePerformanceEntries } from './util/dedupePerformanceEntries';
@@ -144,7 +143,7 @@ export class ReplayContainer {
144143

145144
// If there is no session, then something bad has happened - can't continue
146145
if (!this.session) {
147-
captureInternalException(new Error('Invalid session'));
146+
this.handleException(new Error('No session found'));
148147
return;
149148
}
150149

@@ -192,8 +191,7 @@ export class ReplayContainer {
192191
emit: this.handleRecordingEmit,
193192
});
194193
} catch (err) {
195-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
196-
captureInternalException(err);
194+
this.handleException(err);
197195
}
198196
}
199197

@@ -210,8 +208,7 @@ export class ReplayContainer {
210208
this.eventBuffer?.destroy();
211209
this.eventBuffer = null;
212210
} catch (err) {
213-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
214-
captureInternalException(err);
211+
this.handleException(err);
215212
}
216213
}
217214

@@ -228,8 +225,7 @@ export class ReplayContainer {
228225
this._stopRecording = undefined;
229226
}
230227
} catch (err) {
231-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
232-
captureInternalException(err);
228+
this.handleException(err);
233229
}
234230
}
235231

@@ -244,14 +240,22 @@ export class ReplayContainer {
244240
this.startRecording();
245241
}
246242

243+
/** A wrapper to conditionally capture exceptions. */
244+
handleException(error: unknown): void {
245+
__DEBUG_BUILD__ && logger.error('[Replay]', error);
246+
247+
if (this.options._experiments && this.options._experiments.captureExceptions) {
248+
captureException(error);
249+
}
250+
}
251+
247252
/** for tests only */
248253
clearSession(): void {
249254
try {
250255
deleteSession();
251256
this.session = undefined;
252257
} catch (err) {
253-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
254-
captureInternalException(err);
258+
this.handleException(err);
255259
}
256260
}
257261

@@ -329,8 +333,7 @@ export class ReplayContainer {
329333
this._hasInitializedCoreListeners = true;
330334
}
331335
} catch (err) {
332-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
333-
captureInternalException(err);
336+
this.handleException(err);
334337
}
335338

336339
// _performanceObserver //
@@ -381,8 +384,7 @@ export class ReplayContainer {
381384
this._performanceObserver = null;
382385
}
383386
} catch (err) {
384-
__DEBUG_BUILD__ && logger.error('[Replay]', err);
385-
captureInternalException(err);
387+
this.handleException(err);
386388
}
387389
}
388390

@@ -1013,8 +1015,7 @@ export class ReplayContainer {
10131015
eventContext,
10141016
});
10151017
} catch (err) {
1016-
__DEBUG_BUILD__ && logger.error(err);
1017-
captureInternalException(err);
1018+
this.handleException(err);
10181019
}
10191020
}
10201021

@@ -1207,12 +1208,11 @@ export class ReplayContainer {
12071208
this.resetRetries();
12081209
return true;
12091210
} catch (err) {
1210-
__DEBUG_BUILD__ && logger.error(err);
12111211
// Capture error for every failed replay
12121212
setContext('Replays', {
12131213
_retryCount: this._retryCount,
12141214
});
1215-
captureInternalException(err);
1215+
this.handleException(err);
12161216

12171217
// If an error happened here, it's likely that uploading the attachment
12181218
// failed, we'll can retry with the same events payload

packages/replay/src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ export interface ReplayPluginOptions extends SessionOptions {
112112
* Block all media (e.g. images, svg, video) in recordings.
113113
*/
114114
blockAllMedia: boolean;
115+
116+
/**
117+
* _experiments allows the user to send options to define how this integration works.
118+
*
119+
* Default: undefined
120+
*/
121+
_experiments?: Partial<{ captureExceptions: boolean }>;
115122
}
116123

117124
// These are optional for ReplayPluginOptions because the plugin sets default values

packages/replay/src/util/captureInternalException.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)