0
# Session Replay
1
2
Complete user session recording and playback capabilities for debugging and understanding user behavior through visual reproduction of user sessions.
3
4
## Capabilities
5
6
### Replay Integration
7
8
Core session replay functionality.
9
10
```typescript { .api }
11
/**
12
* Session replay recording integration
13
* @param options - Replay configuration options
14
* @returns Replay integration
15
*/
16
function replayIntegration(options?: ReplayOptions): Integration;
17
18
/**
19
* Canvas recording for session replay
20
* @param options - Canvas replay options
21
* @returns Canvas replay integration
22
*/
23
function replayCanvasIntegration(options?: ReplayCanvasOptions): Integration;
24
25
/**
26
* Get the current replay client instance
27
* @returns Replay client or undefined
28
*/
29
function getReplay(): ReplayClient | undefined;
30
```
31
32
**Usage Example:**
33
34
```typescript
35
import { replayIntegration, replayCanvasIntegration } from "@sentry/browser";
36
37
Sentry.init({
38
dsn: "YOUR_DSN",
39
integrations: [
40
replayIntegration({
41
sessionSampleRate: 0.1, // 10% of sessions
42
errorSampleRate: 1.0, // 100% of error sessions
43
44
// Privacy settings
45
maskAllText: false,
46
maskAllInputs: true,
47
blockAllMedia: true,
48
49
// Performance settings
50
maxReplayDuration: 60 * 60, // 1 hour max
51
sessionSegmentDuration: 5 * 60, // 5 minute segments
52
}),
53
54
replayCanvasIntegration({
55
enableManualSnapshot: true,
56
fps: 4, // 4 frames per second
57
quality: "medium",
58
}),
59
],
60
});
61
```
62
63
## Types
64
65
### Replay Options
66
67
```typescript { .api }
68
interface ReplayOptions {
69
/** Sample rate for normal sessions (0.0 to 1.0) */
70
sessionSampleRate?: number;
71
72
/** Sample rate for error sessions (0.0 to 1.0) */
73
errorSampleRate?: number;
74
75
/** Mask all text content */
76
maskAllText?: boolean;
77
78
/** Mask all input values */
79
maskAllInputs?: boolean;
80
81
/** Block all media elements (images, videos, audio) */
82
blockAllMedia?: boolean;
83
84
/** CSS selectors for elements to mask */
85
maskTextSelectors?: string[];
86
87
/** CSS selectors for elements to block completely */
88
blockSelectors?: string[];
89
90
/** CSS selectors for elements to ignore during recording */
91
ignoreSelectors?: string[];
92
93
/** Maximum replay duration in seconds */
94
maxReplayDuration?: number;
95
96
/** Duration of each session segment in seconds */
97
sessionSegmentDuration?: number;
98
99
/** Minimum duration before sending a replay */
100
minReplayDuration?: number;
101
102
/** Maximum mutations to capture per second */
103
mutationLimit?: number;
104
105
/** Maximum mutations for breadcrumbs */
106
mutationBreadcrumbLimit?: number;
107
108
/** Timeout for slow clicks in milliseconds */
109
slowClickTimeout?: number;
110
111
/** CSS selectors to ignore for slow click detection */
112
slowClickIgnoreSelectors?: string[];
113
114
/** Network request recording options */
115
networkDetailAllowUrls?: (string | RegExp)[];
116
networkDetailDenyUrls?: (string | RegExp)[];
117
networkCaptureBodies?: boolean;
118
networkRequestHeaders?: string[];
119
networkResponseHeaders?: string[];
120
121
/** Privacy configuration */
122
privacy?: {
123
maskAllText?: boolean;
124
maskAllInputs?: boolean;
125
blockAllMedia?: boolean;
126
maskTextSelectors?: string[];
127
blockSelectors?: string[];
128
};
129
130
/** Callback before sending replay */
131
beforeSend?: (event: ReplayEvent, hint: EventHint) => ReplayEvent | null;
132
133
/** Callback before adding breadcrumb to replay */
134
beforeAddRecordingEvent?: (event: RecordingEvent) => RecordingEvent | null;
135
}
136
```
137
138
### Canvas Replay Options
139
140
```typescript { .api }
141
interface ReplayCanvasOptions {
142
/** Enable manual canvas snapshots */
143
enableManualSnapshot?: boolean;
144
145
/** Recording frame rate (fps) */
146
fps?: number;
147
148
/** Recording quality */
149
quality?: "low" | "medium" | "high";
150
151
/** Maximum canvas width to record */
152
maxCanvasWidth?: number;
153
154
/** Maximum canvas height to record */
155
maxCanvasHeight?: number;
156
157
/** Canvas elements to record (CSS selectors) */
158
recordCanvas?: string[];
159
160
/** Canvas elements to ignore (CSS selectors) */
161
ignoreCanvas?: string[];
162
}
163
```
164
165
### Replay Types
166
167
```typescript { .api }
168
interface ReplayClient {
169
/** Start recording a replay */
170
start(): void;
171
172
/** Stop recording */
173
stop(): void;
174
175
/** Check if currently recording */
176
isEnabled(): boolean;
177
178
/** Get current session ID */
179
getSessionId(): string | undefined;
180
181
/** Flush current replay data */
182
flush(): Promise<void>;
183
184
/** Add breadcrumb to replay */
185
addBreadcrumb(breadcrumb: Breadcrumb): void;
186
}
187
188
type ReplayEventType = "custom" | "fullsnapshot" | "incremental" | "meta";
189
190
interface ReplayEventWithTime {
191
type: ReplayEventType;
192
data: any;
193
timestamp: number;
194
}
195
196
interface ReplayBreadcrumbFrame {
197
type: "breadcrumb";
198
category: string;
199
message?: string;
200
level?: SeverityLevel;
201
timestamp: number;
202
data?: any;
203
}
204
205
interface ReplaySpanFrame {
206
type: "span";
207
op: string;
208
description?: string;
209
startTimestamp: number;
210
endTimestamp?: number;
211
data?: any;
212
}
213
214
interface ReplayFrameEvent {
215
type: ReplayEventType;
216
timestamp: number;
217
data: any;
218
}
219
```
220
221
### Replay Event Structure
222
223
```typescript { .api }
224
interface ReplayEvent {
225
type: "replay_event";
226
replay_id: string;
227
segment_id: number;
228
timestamp: number;
229
replay_start_timestamp: number;
230
urls: string[];
231
error_ids: string[];
232
trace_ids: string[];
233
dist?: string;
234
platform: string;
235
environment?: string;
236
release?: string;
237
user?: User;
238
tags?: { [key: string]: string };
239
extra?: { [key: string]: any };
240
}
241
```
242
243
## Privacy and Security
244
245
### Data Masking
246
247
Replay automatically masks sensitive data:
248
249
```typescript
250
replayIntegration({
251
// Text masking
252
maskAllText: false, // Don't mask all text
253
maskTextSelectors: [
254
'.sensitive-data',
255
'[data-private]',
256
'input[type="password"]',
257
'.ssn',
258
'.credit-card',
259
],
260
261
// Input masking
262
maskAllInputs: true, // Mask all input values by default
263
264
// Element blocking
265
blockSelectors: [
266
'.secret-content',
267
'[data-secret]',
268
'iframe[src*="payment"]',
269
],
270
271
// Media blocking
272
blockAllMedia: true, // Block images, videos, audio
273
});
274
```
275
276
### Network Privacy
277
278
Control network request recording:
279
280
```typescript
281
replayIntegration({
282
// Only record specific API calls
283
networkDetailAllowUrls: [
284
/^https:\/\/api\.mysite\.com\/public/,
285
"https://analytics.example.com",
286
],
287
288
// Exclude sensitive endpoints
289
networkDetailDenyUrls: [
290
/\/api\/auth/,
291
/\/api\/payment/,
292
/\/api\/admin/,
293
],
294
295
// Don't capture request/response bodies
296
networkCaptureBodies: false,
297
298
// Only specific headers
299
networkRequestHeaders: ["content-type", "accept"],
300
networkResponseHeaders: ["content-type", "status"],
301
});
302
```
303
304
## Performance Optimization
305
306
### Sampling Strategy
307
308
Use different sampling rates for different scenarios:
309
310
```typescript
311
replayIntegration({
312
// Low sampling for normal sessions to reduce bandwidth
313
sessionSampleRate: 0.01, // 1% of sessions
314
315
// High sampling for error sessions for debugging
316
errorSampleRate: 1.0, // 100% of error sessions
317
318
// Limit replay duration to control storage
319
maxReplayDuration: 30 * 60, // 30 minutes max
320
321
// Smaller segments for better streaming
322
sessionSegmentDuration: 2 * 60, // 2 minute segments
323
324
// Performance limits
325
mutationLimit: 10000, // Limit DOM changes per second
326
slowClickTimeout: 7000, // 7 second slow click threshold
327
});
328
```
329
330
### Conditional Recording
331
332
Start/stop recording based on conditions:
333
334
```typescript
335
import { getReplay } from "@sentry/browser";
336
337
// Start recording on user action
338
function startRecordingSession() {
339
const replay = getReplay();
340
if (replay) {
341
replay.start();
342
}
343
}
344
345
// Stop recording when leaving sensitive area
346
function stopRecordingForPrivacy() {
347
const replay = getReplay();
348
if (replay) {
349
replay.stop();
350
}
351
}
352
353
// Conditional recording based on user consent
354
if (userHasConsentedToRecording) {
355
startRecordingSession();
356
}
357
```
358
359
## Canvas Recording
360
361
Record HTML5 canvas elements:
362
363
```typescript
364
replayCanvasIntegration({
365
// Record specific canvas elements
366
recordCanvas: ["#game-canvas", ".chart-canvas"],
367
368
// Performance settings
369
fps: 2, // Low frame rate for performance
370
quality: "medium",
371
372
// Size limits
373
maxCanvasWidth: 1920,
374
maxCanvasHeight: 1080,
375
376
// Manual snapshot mode for better performance
377
enableManualSnapshot: true,
378
});
379
```
380
381
## Best Practices
382
383
### Privacy-First Configuration
384
385
```typescript {.api}
386
replayIntegration({
387
// Conservative privacy defaults
388
maskAllInputs: true,
389
blockAllMedia: true,
390
maskTextSelectors: [".pii", "[data-sensitive]"],
391
blockSelectors: [".admin-only", "[data-secret]"],
392
393
// No network details by default
394
networkDetailAllowUrls: [],
395
networkCaptureBodies: false,
396
397
// Before send filtering
398
beforeSend: (event) => {
399
// Additional privacy checks
400
if (containsSensitiveData(event)) {
401
return null;
402
}
403
return event;
404
},
405
});
406
```