1
1
import { getCurrentHub } from '@sentry/core';
2
2
import type { BrowserClientReplayOptions, Integration } from '@sentry/types';
3
+ import { dropUndefinedKeys } from '@sentry/utils';
3
4
4
5
import { DEFAULT_FLUSH_MAX_DELAY, DEFAULT_FLUSH_MIN_DELAY, MASK_ALL_TEXT_SELECTOR } from './constants';
5
6
import { ReplayContainer } from './replay';
@@ -10,6 +11,9 @@ const MEDIA_SELECTORS = 'img,image,svg,path,rect,area,video,object,picture,embed
10
11
11
12
let _initialized = false;
12
13
14
+ type InitialReplayPluginOptions = Omit<ReplayPluginOptions, 'sessionSampleRate' | 'errorSampleRate'> &
15
+ Partial<Pick<ReplayPluginOptions, 'sessionSampleRate' | 'errorSampleRate'>>;
16
+
13
17
/**
14
18
* The main replay integration class, to be passed to `init({ integrations: [] })`.
15
19
*/
@@ -29,7 +33,14 @@ export class Replay implements Integration {
29
33
*/
30
34
private readonly _recordingOptions: RecordingOptions;
31
35
32
- private readonly _options: ReplayPluginOptions;
36
+ /**
37
+ * Initial options passed to the replay integration, merged with default values.
38
+ * Note: `sessionSampleRate` and `errorSampleRate` are not required here, as they
39
+ * can only be finally set when setupOnce() is called.
40
+ *
41
+ * @private
42
+ */
43
+ private readonly _initialOptions: InitialReplayPluginOptions;
33
44
34
45
private _replay?: ReplayContainer;
35
46
@@ -61,12 +72,12 @@ export class Replay implements Integration {
61
72
..._recordingOptions,
62
73
};
63
74
64
- this._options = {
75
+ this._initialOptions = {
65
76
flushMinDelay,
66
77
flushMaxDelay,
67
78
stickySession,
68
- sessionSampleRate: 0 ,
69
- errorSampleRate: 0 ,
79
+ sessionSampleRate,
80
+ errorSampleRate,
70
81
useCompression,
71
82
maskAllText: typeof maskAllText === 'boolean' ? maskAllText : !maskTextSelector,
72
83
blockAllMedia,
@@ -82,7 +93,7 @@ Instead, configure \`replaysSessionSampleRate\` directly in the SDK init options
82
93
Sentry.init({ replaysSessionSampleRate: ${sessionSampleRate} })`,
83
94
);
84
95
85
- this._options .sessionSampleRate = sessionSampleRate;
96
+ this._initialOptions .sessionSampleRate = sessionSampleRate;
86
97
}
87
98
88
99
if (typeof errorSampleRate === 'number') {
@@ -94,17 +105,17 @@ Instead, configure \`replaysOnErrorSampleRate\` directly in the SDK init options
94
105
Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
95
106
);
96
107
97
- this._options .errorSampleRate = errorSampleRate;
108
+ this._initialOptions .errorSampleRate = errorSampleRate;
98
109
}
99
110
100
- if (this._options .maskAllText) {
111
+ if (this._initialOptions .maskAllText) {
101
112
// `maskAllText` is a more user friendly option to configure
102
113
// `maskTextSelector`. This means that all nodes will have their text
103
114
// content masked.
104
115
this._recordingOptions.maskTextSelector = MASK_ALL_TEXT_SELECTOR;
105
116
}
106
117
107
- if (this._options .blockAllMedia) {
118
+ if (this._initialOptions .blockAllMedia) {
108
119
// `blockAllMedia` is a more user friendly option to configure blocking
109
120
// embedded media elements
110
121
this._recordingOptions.blockSelector = !this._recordingOptions.blockSelector
@@ -190,30 +201,45 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
190
201
/** Setup the integration. */
191
202
private _setup(): void {
192
203
// Client is not available in constructor, so we need to wait until setupOnce
193
- this._loadReplayOptionsFromClient();
194
-
195
- if (!this._options.sessionSampleRate && !this._options.errorSampleRate) {
196
- // eslint-disable-next-line no-console
197
- console.warn('Replay is disabled because both `replaysSessionSampleRate` and `replaysOnErrorSampleRate` are 0');
198
- }
204
+ const finalOptions = this._loadReplayOptionsFromClient(this._initialOptions);
199
205
200
206
this._replay = new ReplayContainer({
201
- options: this._options ,
207
+ options: finalOptions ,
202
208
recordingOptions: this._recordingOptions,
203
209
});
204
210
}
205
211
206
212
/** Parse Replay-related options from SDK options */
207
- private _loadReplayOptionsFromClient(): void {
213
+ private _loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions ): ReplayPluginOptions {
208
214
const client = getCurrentHub().getClient();
209
215
const opt = client && (client.getOptions() as BrowserClientReplayOptions | undefined);
210
216
211
- if (opt && typeof opt.replaysSessionSampleRate === 'number') {
212
- this._options.sessionSampleRate = opt.replaysSessionSampleRate;
217
+ const finalOptions = { sessionSampleRate: 0, errorSampleRate: 0, ...dropUndefinedKeys(initialOptions) };
218
+
219
+ if (!opt) {
220
+ return finalOptions;
213
221
}
214
222
215
- if (opt && typeof opt.replaysOnErrorSampleRate === 'number') {
216
- this._options.errorSampleRate = opt.replaysOnErrorSampleRate;
223
+ if (
224
+ initialOptions.sessionSampleRate == null && // TODO remove once deprecated rates are removed
225
+ initialOptions.errorSampleRate == null && // TODO remove once deprecated rates are removed
226
+ opt.replaysSessionSampleRate == null &&
227
+ opt.replaysOnErrorSampleRate == null
228
+ ) {
229
+ // eslint-disable-next-line no-console
230
+ console.warn(
231
+ 'Replay is disabled because neither `replaysSessionSampleRate` nor `replaysOnErrorSampleRate` are set',
232
+ );
233
+ }
234
+
235
+ if (typeof opt.replaysSessionSampleRate === 'number') {
236
+ finalOptions.sessionSampleRate = opt.replaysSessionSampleRate;
237
+ }
238
+
239
+ if (typeof opt.replaysOnErrorSampleRate === 'number') {
240
+ finalOptions.errorSampleRate = opt.replaysOnErrorSampleRate;
217
241
}
242
+
243
+ return finalOptions;
218
244
}
219
245
}
0 commit comments