@spanwise/rum 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -9
- package/dist/client.d.ts +9 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -2
- package/dist/client.js.map +1 -1
- package/dist/replay.d.ts +14 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +131 -52
- package/dist/replay.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,17 +116,25 @@ Get the current session ID.
|
|
|
116
116
|
const sessionId = spanwise.getSessionId()
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
### `spanwise.
|
|
119
|
+
### `spanwise.forceReplayUpload()`
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
Force replay upload for specific users (bypasses sampling).
|
|
122
122
|
|
|
123
123
|
```typescript
|
|
124
|
-
//
|
|
124
|
+
// Force upload for VIP users regardless of sample rate
|
|
125
125
|
if (user.isVIP) {
|
|
126
|
-
spanwise.
|
|
126
|
+
spanwise.forceReplayUpload()
|
|
127
127
|
}
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
### `spanwise.stopReplay()`
|
|
131
|
+
|
|
132
|
+
Stop replay recording entirely.
|
|
133
|
+
|
|
134
|
+
### `spanwise.isReplayUploading()`
|
|
135
|
+
|
|
136
|
+
Check if replay is currently uploading to server (vs buffering in memory).
|
|
137
|
+
|
|
130
138
|
---
|
|
131
139
|
|
|
132
140
|
## Session Replay
|
|
@@ -144,19 +152,32 @@ const spanwise = createSpanwiseBrowser({
|
|
|
144
152
|
})
|
|
145
153
|
```
|
|
146
154
|
|
|
147
|
-
###
|
|
155
|
+
### How It Works: Rolling Buffer
|
|
148
156
|
|
|
149
|
-
|
|
157
|
+
Session Replay uses a **rolling buffer architecture** (similar to Sentry):
|
|
158
|
+
|
|
159
|
+
1. **Always recording** - When enabled, the SDK always records to a 60-second memory buffer
|
|
160
|
+
2. **Sampled sessions** (default 10%) - Upload immediately to server
|
|
161
|
+
3. **Non-sampled sessions** (90%) - Keep buffer in memory, zero network cost
|
|
162
|
+
4. **On error** - Flush the 60-second buffer and start uploading
|
|
163
|
+
|
|
164
|
+
This means you **always capture what happened before an error**, not just after.
|
|
165
|
+
|
|
166
|
+
### Sampling
|
|
150
167
|
|
|
151
168
|
```typescript
|
|
152
169
|
replay: {
|
|
153
170
|
enabled: true,
|
|
154
|
-
sampleRate: 0.1, // 10%
|
|
155
|
-
onErrorSampleRate: 1.0, // 100%
|
|
171
|
+
sampleRate: 0.1, // 10% upload immediately
|
|
172
|
+
onErrorSampleRate: 1.0, // 100% upload on error (includes 60s buffer)
|
|
156
173
|
}
|
|
157
174
|
```
|
|
158
175
|
|
|
159
|
-
|
|
176
|
+
| Scenario | What's Captured |
|
|
177
|
+
|----------|-----------------|
|
|
178
|
+
| Sampled (10%) | Full session from start |
|
|
179
|
+
| Not sampled + error | 60 seconds before error + everything after |
|
|
180
|
+
| Not sampled + no error | Nothing sent (zero network cost) |
|
|
160
181
|
|
|
161
182
|
---
|
|
162
183
|
|
package/dist/client.d.ts
CHANGED
|
@@ -42,6 +42,10 @@ export declare function createSpanwiseBrowser(config: BrowserConfig): {
|
|
|
42
42
|
getSessionId: () => null;
|
|
43
43
|
startReplay: () => void;
|
|
44
44
|
stopReplay: () => void;
|
|
45
|
+
/** Force replay upload (e.g., for VIP users) - overrides sampling */
|
|
46
|
+
forceReplayUpload?: undefined;
|
|
47
|
+
/** Check if replay is currently uploading to server */
|
|
48
|
+
isReplayUploading?: undefined;
|
|
45
49
|
} | {
|
|
46
50
|
trackEvent: (name: string, properties?: Record<string, unknown>) => void;
|
|
47
51
|
trackPageView: (url?: string) => void;
|
|
@@ -51,10 +55,13 @@ export declare function createSpanwiseBrowser(config: BrowserConfig): {
|
|
|
51
55
|
}) => void;
|
|
52
56
|
setUser: (id: string, traits?: Record<string, unknown>) => void;
|
|
53
57
|
getSessionId: () => string;
|
|
54
|
-
/**
|
|
55
|
-
|
|
58
|
+
/** Force replay upload (e.g., for VIP users) - overrides sampling */
|
|
59
|
+
forceReplayUpload: () => void | undefined;
|
|
56
60
|
/** Stop replay recording */
|
|
57
61
|
stopReplay: () => void | undefined;
|
|
62
|
+
/** Check if replay is currently uploading to server */
|
|
63
|
+
isReplayUploading: () => boolean;
|
|
64
|
+
startReplay?: undefined;
|
|
58
65
|
};
|
|
59
66
|
export type SpanwiseBrowser = ReturnType<typeof createSpanwiseBrowser>;
|
|
60
67
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,YAAY,EAAwB,MAAM,aAAa,CAAA;AACrE,OAAO,EACN,KAAK,WAAW,EAIhB,MAAM,cAAc,CAAA;AAIrB,MAAM,MAAM,aAAa,GAAG;IAC3B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACxC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,wCAAwC;IACxC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,WAAW,CAAA;IAC5B,mCAAmC;IACnC,MAAM,CAAC,EAAE,YAAY,CAAA;CACrB,CAAA;AAmBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,YAAY,EAAwB,MAAM,aAAa,CAAA;AACrE,OAAO,EACN,KAAK,WAAW,EAIhB,MAAM,cAAc,CAAA;AAIrB,MAAM,MAAM,aAAa,GAAG;IAC3B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACxC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,wCAAwC;IACxC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,WAAW,CAAA;IAC5B,mCAAmC;IACnC,MAAM,CAAC,EAAE,YAAY,CAAA;CACrB,CAAA;AAmBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa;;;;;;;;IA2NzD,qEAAqE;;IAIrE,uDAAuD;;;uBAxKjD,MAAM,eACC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAClC,IAAI;0BAhBsB,MAAM,KAAG,IAAI;wBA6BlC,KAAK,YACF;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAChD,IAAI;kBAOc,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAWtC,MAAM;IAiInC,qEAAqE;;IAErE,4BAA4B;;IAE5B,uDAAuD;;;EAGxD;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA"}
|
package/dist/client.js
CHANGED
|
@@ -196,10 +196,12 @@ export function createSpanwiseBrowser(config) {
|
|
|
196
196
|
trackError,
|
|
197
197
|
setUser,
|
|
198
198
|
getSessionId: getSessionIdValue,
|
|
199
|
-
/**
|
|
200
|
-
|
|
199
|
+
/** Force replay upload (e.g., for VIP users) - overrides sampling */
|
|
200
|
+
forceReplayUpload: () => replayRecorder?.startUploading(),
|
|
201
201
|
/** Stop replay recording */
|
|
202
202
|
stopReplay: () => replayRecorder?.stop(),
|
|
203
|
+
/** Check if replay is currently uploading to server */
|
|
204
|
+
isReplayUploading: () => replayRecorder?.isUploading() ?? false,
|
|
203
205
|
};
|
|
204
206
|
}
|
|
205
207
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/replay.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type PrivacyMode = "strict" | "balanced" | "permissive";
|
|
|
14
14
|
export type ReplayConfig = {
|
|
15
15
|
/** Enable replay recording (default: false) */
|
|
16
16
|
enabled?: boolean;
|
|
17
|
-
/** Sample rate for
|
|
17
|
+
/** Sample rate for immediate upload 0-1 (default: 0.1 = 10%) */
|
|
18
18
|
sampleRate?: number;
|
|
19
19
|
/** Sample rate when error occurs 0-1 (default: 1.0 = 100%) */
|
|
20
20
|
onErrorSampleRate?: number;
|
|
@@ -41,12 +41,25 @@ type ReplayTransportConfig = {
|
|
|
41
41
|
baseUrl: string;
|
|
42
42
|
sessionId: string;
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Session Replay Recorder with Rolling Buffer
|
|
46
|
+
*
|
|
47
|
+
* Architecture:
|
|
48
|
+
* - Always records to memory when enabled
|
|
49
|
+
* - If sampled (sampleRate): uploads immediately
|
|
50
|
+
* - If not sampled: keeps 60s rolling buffer in memory
|
|
51
|
+
* - On error: flushes buffer and starts uploading (if onErrorSampleRate passes)
|
|
52
|
+
* - Zero network cost for sessions without errors that weren't sampled
|
|
53
|
+
*/
|
|
44
54
|
export declare function createReplayRecorder(config: ReplayConfig, transportConfig: ReplayTransportConfig, onError?: () => void): {
|
|
45
55
|
start: () => void;
|
|
46
56
|
stop: () => void;
|
|
47
57
|
markError: () => void;
|
|
48
58
|
isRecording: () => boolean;
|
|
59
|
+
isUploading: () => boolean;
|
|
49
60
|
wasUpgradedByError: () => boolean;
|
|
61
|
+
/** Force switch to upload mode (for manual control) */
|
|
62
|
+
startUploading: () => void;
|
|
50
63
|
};
|
|
51
64
|
export type ReplayRecorder = ReturnType<typeof createReplayRecorder>;
|
|
52
65
|
export {};
|
package/dist/replay.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAA;AAE9D,MAAM,MAAM,YAAY,GAAG;IAC1B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAA;AAE9D,MAAM,MAAM,YAAY,GAAG;IAC1B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CACzB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAqBD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,YAAY,EACpB,eAAe,EAAE,qBAAqB,EACtC,OAAO,CAAC,EAAE,MAAM,IAAI;iBA2LF,IAAI;gBAuBL,IAAI;qBA6CC,IAAI;;;;IA4BzB,uDAAuD;0BAjHzB,IAAI;EAoHnC;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
|
package/dist/replay.js
CHANGED
|
@@ -2,11 +2,13 @@ import { gzipSync } from "fflate";
|
|
|
2
2
|
import { record } from "rrweb";
|
|
3
3
|
const MAX_CHUNK_SIZE = 64 * 1024; // 64KB uncompressed
|
|
4
4
|
const FLUSH_INTERVAL = 5000; // 5 seconds
|
|
5
|
+
const BUFFER_DURATION_MS = 60_000; // 60 seconds rolling buffer
|
|
6
|
+
const BUFFER_CLEANUP_INTERVAL = 10_000; // Cleanup every 10 seconds
|
|
5
7
|
// Selectors for privacy control
|
|
6
8
|
const BLOCK_SELECTOR = "[data-sw-block], .rr-block";
|
|
7
9
|
const MASK_SELECTOR = "[data-sw-mask], .rr-mask";
|
|
8
10
|
const UNMASK_SELECTOR = "[data-sw-unmask]";
|
|
9
|
-
// Efficient base64 encoding for Uint8Array
|
|
11
|
+
// Efficient base64 encoding for Uint8Array
|
|
10
12
|
function uint8ToBase64(bytes) {
|
|
11
13
|
let binary = "";
|
|
12
14
|
for (const byte of bytes) {
|
|
@@ -14,41 +16,49 @@ function uint8ToBase64(bytes) {
|
|
|
14
16
|
}
|
|
15
17
|
return btoa(binary);
|
|
16
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Session Replay Recorder with Rolling Buffer
|
|
21
|
+
*
|
|
22
|
+
* Architecture:
|
|
23
|
+
* - Always records to memory when enabled
|
|
24
|
+
* - If sampled (sampleRate): uploads immediately
|
|
25
|
+
* - If not sampled: keeps 60s rolling buffer in memory
|
|
26
|
+
* - On error: flushes buffer and starts uploading (if onErrorSampleRate passes)
|
|
27
|
+
* - Zero network cost for sessions without errors that weren't sampled
|
|
28
|
+
*/
|
|
17
29
|
export function createReplayRecorder(config, transportConfig, onError) {
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
// Event buffer - always populated while recording
|
|
31
|
+
const buffer = [];
|
|
32
|
+
let estimatedSize = 0;
|
|
33
|
+
// Upload state
|
|
20
34
|
let chunkIndex = 0;
|
|
21
35
|
let flushTimer = null;
|
|
36
|
+
let bufferCleanupTimer = null;
|
|
37
|
+
// Recording state
|
|
22
38
|
let isRecording = false;
|
|
23
|
-
let
|
|
24
|
-
let stopRecording = null;
|
|
39
|
+
let stopRecordingFn = null;
|
|
25
40
|
let hasErrors = false;
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
let mode = "buffer";
|
|
42
|
+
// Sampling decisions (made once at session start)
|
|
43
|
+
const shouldUploadImmediately = Math.random() < (config.sampleRate ?? 0.1);
|
|
28
44
|
let wasUpgradedByError = false;
|
|
29
45
|
function getRecordOptions() {
|
|
30
46
|
const privacyMode = config.privacyMode ?? "strict";
|
|
31
|
-
// Build privacy settings based on mode
|
|
32
47
|
const maskAllInputs = privacyMode !== "permissive";
|
|
33
48
|
const maskAllText = privacyMode === "strict";
|
|
34
|
-
// In strict mode, mask everything except explicitly unmasked elements
|
|
35
|
-
// In balanced/permissive modes, only mask elements with data-sw-mask
|
|
36
|
-
const maskTextSelector = maskAllText
|
|
37
|
-
? `*:not(${UNMASK_SELECTOR}):not(${UNMASK_SELECTOR} *)`
|
|
38
|
-
: MASK_SELECTOR;
|
|
39
49
|
return {
|
|
40
|
-
emit:
|
|
50
|
+
emit: handleEvent,
|
|
41
51
|
sampling: {
|
|
42
52
|
mousemove: true,
|
|
43
53
|
mouseInteraction: true,
|
|
44
54
|
scroll: 150,
|
|
45
55
|
input: "last",
|
|
46
56
|
},
|
|
47
|
-
// Privacy settings
|
|
48
57
|
maskAllInputs,
|
|
49
|
-
|
|
58
|
+
maskAllText,
|
|
59
|
+
maskTextSelector: maskAllText ? undefined : MASK_SELECTOR,
|
|
60
|
+
unmaskTextSelector: maskAllText ? UNMASK_SELECTOR : undefined,
|
|
50
61
|
blockSelector: BLOCK_SELECTOR,
|
|
51
|
-
// Slimmer DOM for performance
|
|
52
62
|
slimDOMOptions: {
|
|
53
63
|
script: true,
|
|
54
64
|
comment: true,
|
|
@@ -63,18 +73,21 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
63
73
|
};
|
|
64
74
|
}
|
|
65
75
|
function handleEvent(event) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
buffer.push(event);
|
|
77
|
+
estimatedSize += JSON.stringify(event).length + 1;
|
|
78
|
+
if (mode === "upload") {
|
|
79
|
+
// In upload mode, flush when chunk is large enough
|
|
80
|
+
if (estimatedSize >= MAX_CHUNK_SIZE) {
|
|
81
|
+
flush();
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
scheduleFlush();
|
|
85
|
+
}
|
|
74
86
|
}
|
|
87
|
+
// In buffer mode, events just accumulate (cleaned up periodically)
|
|
75
88
|
}
|
|
76
89
|
function scheduleFlush() {
|
|
77
|
-
if (flushTimer)
|
|
90
|
+
if (flushTimer || mode !== "upload")
|
|
78
91
|
return;
|
|
79
92
|
flushTimer = setTimeout(() => {
|
|
80
93
|
flushTimer = null;
|
|
@@ -83,20 +96,19 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
83
96
|
}
|
|
84
97
|
function preparePayload(batch) {
|
|
85
98
|
const compressed = gzipSync(new TextEncoder().encode(JSON.stringify(batch)));
|
|
86
|
-
const isFullSnapshot = chunkIndex === 0;
|
|
87
99
|
return JSON.stringify({
|
|
88
100
|
sessionId: transportConfig.sessionId,
|
|
89
101
|
chunkIndex,
|
|
90
102
|
data: uint8ToBase64(compressed),
|
|
91
|
-
isFullSnapshot,
|
|
103
|
+
isFullSnapshot: chunkIndex === 0,
|
|
92
104
|
timestamp: Date.now(),
|
|
93
105
|
hasErrors,
|
|
94
106
|
});
|
|
95
107
|
}
|
|
96
108
|
async function flush() {
|
|
97
|
-
if (
|
|
109
|
+
if (buffer.length === 0 || mode !== "upload")
|
|
98
110
|
return;
|
|
99
|
-
const batch =
|
|
111
|
+
const batch = buffer.splice(0);
|
|
100
112
|
estimatedSize = 0;
|
|
101
113
|
try {
|
|
102
114
|
await fetch(`${transportConfig.baseUrl}/v1/ingest/replays`, {
|
|
@@ -115,9 +127,9 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
115
127
|
}
|
|
116
128
|
}
|
|
117
129
|
function flushBeacon() {
|
|
118
|
-
if (
|
|
130
|
+
if (buffer.length === 0 || mode !== "upload")
|
|
119
131
|
return;
|
|
120
|
-
const batch =
|
|
132
|
+
const batch = buffer.splice(0);
|
|
121
133
|
estimatedSize = 0;
|
|
122
134
|
try {
|
|
123
135
|
fetch(`${transportConfig.baseUrl}/v1/ingest/replays`, {
|
|
@@ -137,13 +149,64 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
137
149
|
// Ignore errors during page unload
|
|
138
150
|
}
|
|
139
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Clean up old events from buffer (only in buffer mode)
|
|
154
|
+
* Keeps last 60 seconds of events
|
|
155
|
+
*/
|
|
156
|
+
function cleanupBuffer() {
|
|
157
|
+
if (mode !== "buffer" || buffer.length === 0)
|
|
158
|
+
return;
|
|
159
|
+
const cutoff = Date.now() - BUFFER_DURATION_MS;
|
|
160
|
+
let removeCount = 0;
|
|
161
|
+
// Find how many events to remove (they're chronologically ordered)
|
|
162
|
+
for (const event of buffer) {
|
|
163
|
+
if (event.timestamp < cutoff) {
|
|
164
|
+
removeCount++;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (removeCount > 0) {
|
|
171
|
+
buffer.splice(0, removeCount);
|
|
172
|
+
// Recalculate size estimate
|
|
173
|
+
estimatedSize = buffer.reduce((sum, e) => sum + JSON.stringify(e).length + 1, 0);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Switch from buffer mode to upload mode
|
|
178
|
+
* Flushes the entire buffer and starts uploading
|
|
179
|
+
*/
|
|
180
|
+
function switchToUploadMode() {
|
|
181
|
+
if (mode === "upload")
|
|
182
|
+
return;
|
|
183
|
+
mode = "upload";
|
|
184
|
+
// Stop buffer cleanup
|
|
185
|
+
if (bufferCleanupTimer) {
|
|
186
|
+
clearInterval(bufferCleanupTimer);
|
|
187
|
+
bufferCleanupTimer = null;
|
|
188
|
+
}
|
|
189
|
+
// Flush the buffer immediately
|
|
190
|
+
if (buffer.length > 0) {
|
|
191
|
+
flush();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
140
194
|
function start() {
|
|
141
|
-
if (isRecording
|
|
195
|
+
if (isRecording)
|
|
142
196
|
return;
|
|
143
|
-
hasStartedRecording = true;
|
|
144
197
|
isRecording = true;
|
|
198
|
+
// Determine initial mode
|
|
199
|
+
if (shouldUploadImmediately) {
|
|
200
|
+
mode = "upload";
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
mode = "buffer";
|
|
204
|
+
// Start buffer cleanup interval
|
|
205
|
+
bufferCleanupTimer = setInterval(cleanupBuffer, BUFFER_CLEANUP_INTERVAL);
|
|
206
|
+
}
|
|
207
|
+
// Start rrweb recording
|
|
145
208
|
const stop = record(getRecordOptions());
|
|
146
|
-
|
|
209
|
+
stopRecordingFn = stop ?? null;
|
|
147
210
|
// Setup unload handlers
|
|
148
211
|
window.addEventListener("visibilitychange", handleVisibilityChange);
|
|
149
212
|
window.addEventListener("pagehide", handlePageHide);
|
|
@@ -152,41 +215,54 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
152
215
|
if (!isRecording)
|
|
153
216
|
return;
|
|
154
217
|
isRecording = false;
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
|
|
218
|
+
if (stopRecordingFn) {
|
|
219
|
+
stopRecordingFn();
|
|
220
|
+
stopRecordingFn = null;
|
|
158
221
|
}
|
|
159
222
|
if (flushTimer) {
|
|
160
223
|
clearTimeout(flushTimer);
|
|
161
224
|
flushTimer = null;
|
|
162
225
|
}
|
|
163
|
-
|
|
164
|
-
|
|
226
|
+
if (bufferCleanupTimer) {
|
|
227
|
+
clearInterval(bufferCleanupTimer);
|
|
228
|
+
bufferCleanupTimer = null;
|
|
229
|
+
}
|
|
230
|
+
// Final flush only if in upload mode
|
|
231
|
+
if (mode === "upload") {
|
|
232
|
+
flush();
|
|
233
|
+
}
|
|
165
234
|
window.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
166
235
|
window.removeEventListener("pagehide", handlePageHide);
|
|
167
236
|
}
|
|
168
237
|
function handleVisibilityChange() {
|
|
169
|
-
if (document.visibilityState === "hidden") {
|
|
238
|
+
if (document.visibilityState === "hidden" && mode === "upload") {
|
|
170
239
|
flushBeacon();
|
|
171
240
|
}
|
|
172
241
|
}
|
|
173
242
|
function handlePageHide() {
|
|
174
|
-
|
|
243
|
+
if (mode === "upload") {
|
|
244
|
+
flushBeacon();
|
|
245
|
+
}
|
|
175
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Mark that an error occurred in this session
|
|
249
|
+
* If in buffer mode, switches to upload mode (subject to onErrorSampleRate)
|
|
250
|
+
*/
|
|
176
251
|
function markError() {
|
|
177
252
|
hasErrors = true;
|
|
178
|
-
//
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
253
|
+
// If already uploading, nothing to do
|
|
254
|
+
if (mode === "upload")
|
|
255
|
+
return;
|
|
256
|
+
// Check if we should upgrade to upload mode
|
|
257
|
+
const onErrorRate = config.onErrorSampleRate ?? 1.0;
|
|
258
|
+
if (Math.random() < onErrorRate) {
|
|
259
|
+
wasUpgradedByError = true;
|
|
260
|
+
switchToUploadMode();
|
|
261
|
+
onError?.();
|
|
186
262
|
}
|
|
187
263
|
}
|
|
188
|
-
// Auto-start
|
|
189
|
-
if (config.enabled
|
|
264
|
+
// Auto-start recording when enabled
|
|
265
|
+
if (config.enabled) {
|
|
190
266
|
// Defer to next tick to ensure DOM is ready
|
|
191
267
|
setTimeout(start, 0);
|
|
192
268
|
}
|
|
@@ -195,7 +271,10 @@ export function createReplayRecorder(config, transportConfig, onError) {
|
|
|
195
271
|
stop,
|
|
196
272
|
markError,
|
|
197
273
|
isRecording: () => isRecording,
|
|
274
|
+
isUploading: () => mode === "upload",
|
|
198
275
|
wasUpgradedByError: () => wasUpgradedByError,
|
|
276
|
+
/** Force switch to upload mode (for manual control) */
|
|
277
|
+
startUploading: switchToUploadMode,
|
|
199
278
|
};
|
|
200
279
|
}
|
|
201
280
|
//# sourceMappingURL=replay.js.map
|
package/dist/replay.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAgD9B,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,oBAAoB;AACrD,MAAM,cAAc,GAAG,IAAI,CAAA,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"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"}
|