@multiplayer-app/session-recorder-browser 2.0.18 → 2.0.24
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 +14 -3
- package/dist/browser/index.js +102 -32
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +6 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/exporters/index.js +1 -1
- package/dist/exporters/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -33
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +102 -32
- package/dist/index.umd.js.map +1 -1
- package/dist/rrweb/index.d.ts +1 -0
- package/dist/rrweb/index.d.ts.map +1 -1
- package/dist/rrweb/index.js +10 -2
- package/dist/rrweb/index.js.map +1 -1
- package/dist/services/crashBuffer.service.d.ts +2 -1
- package/dist/services/crashBuffer.service.d.ts.map +1 -1
- package/dist/services/crashBuffer.service.js +5 -1
- package/dist/services/crashBuffer.service.js.map +1 -1
- package/dist/services/socket.service.d.ts +3 -0
- package/dist/services/socket.service.d.ts.map +1 -1
- package/dist/services/socket.service.js +47 -5
- package/dist/services/socket.service.js.map +1 -1
- package/dist/session-recorder.d.ts.map +1 -1
- package/dist/session-recorder.js +31 -20
- package/dist/session-recorder.js.map +1 -1
- package/dist/types/session-recorder.d.ts +5 -2
- package/dist/types/session-recorder.d.ts.map +1 -1
- package/dist/types/session-recorder.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -98,8 +98,8 @@ SessionRecorder.init({
|
|
|
98
98
|
|
|
99
99
|
showWidget: true, // show in‑app recording widget (default: true)
|
|
100
100
|
recordCanvas: true, // record canvas elements (default: false)
|
|
101
|
-
inlineImages: true, // inline images as base64
|
|
102
|
-
inlineStylesheet: true, // inline stylesheets
|
|
101
|
+
inlineImages: true, // opt-in: inline images as base64 (requires CORS on cross-origin asset hosts; default: false)
|
|
102
|
+
inlineStylesheet: true, // opt-in: inline stylesheets (cross-origin hosts may need CORS; default: false)
|
|
103
103
|
// Add domains to not capture OTLP data in the session recording
|
|
104
104
|
ignoreUrls: [
|
|
105
105
|
/https:\/\/domain\.to\.ignore\/.*/, // can be regex or string
|
|
@@ -119,7 +119,7 @@ SessionRecorder.init({
|
|
|
119
119
|
// crash buffer: keep a rolling window of rrweb + traces when no recording is active.
|
|
120
120
|
// when user starts a session or saves (e.g. on error), the buffer is flushed into the session.
|
|
121
121
|
buffering: {
|
|
122
|
-
enabled:
|
|
122
|
+
enabled: true, // enable/disable buffering (default: true)
|
|
123
123
|
windowMinutes: 0.5, // rolling window size in minutes (default: 0.5)
|
|
124
124
|
snapshotIntervalMs: 20000 // full snapshot interval while buffering in ms (default: 20000)
|
|
125
125
|
},
|
|
@@ -222,6 +222,15 @@ SessionRecorder.init({
|
|
|
222
222
|
})
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
+
### Important: Inlining images and stylesheets (CORS)
|
|
226
|
+
|
|
227
|
+
By default, **`inlineImages`** and **`inlineStylesheet`** are **`false`**. That avoids failed cross-origin requests and DevTools noise when assets are served from another host (for example S3 or a CDN) that does not send CORS headers such as **`Access-Control-Allow-Origin`** for your app.
|
|
228
|
+
|
|
229
|
+
If you enable either option:
|
|
230
|
+
|
|
231
|
+
- The browser must be allowed to **read** those resources from script (image pixels for base64 inlining, or stylesheet text for inlining). Configure CORS on the asset host for your frontend origin, or serve assets same-origin via a proxy.
|
|
232
|
+
- With defaults left off, recordings still store normal **`src`** and stylesheet links; replay loads them like a normal page when URLs remain valid.
|
|
233
|
+
|
|
225
234
|
### Manual session recording
|
|
226
235
|
|
|
227
236
|
Below is an example showing how to create a session recording in `MANUAL` mode. Manual session recordings stream and save all the data between calling `start` and `stop`.
|
|
@@ -388,6 +397,8 @@ For React Native applications (iOS and Android), use the dedicated React Native
|
|
|
388
397
|
|
|
389
398
|
For more details on how the Multiplayer Session Recorder integrates with your backend architecture and system auto-documentation, check out our [official documentation](https://www.multiplayer.app/docs/features/system-auto-documentation/).
|
|
390
399
|
|
|
400
|
+
**Inlining and CORS:** See [Inlining images and stylesheets (CORS)](#important-inlining-images-and-stylesheets-cors) above for defaults and when you must configure CORS on asset hosts.
|
|
401
|
+
|
|
391
402
|
## License
|
|
392
403
|
|
|
393
404
|
This library is distributed under the [MIT License](./LICENSE).
|
package/dist/browser/index.js
CHANGED
|
@@ -25163,7 +25163,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
|
|
|
25163
25163
|
const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
|
|
25164
25164
|
const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
|
|
25165
25165
|
const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
|
|
25166
|
-
const PACKAGE_VERSION_EXPORT = "2.0.
|
|
25166
|
+
const PACKAGE_VERSION_EXPORT = "2.0.24" || 0;
|
|
25167
25167
|
// Regex patterns for OpenTelemetry ignore URLs
|
|
25168
25168
|
const OTEL_IGNORE_URLS = [
|
|
25169
25169
|
// Traces endpoint
|
|
@@ -25249,8 +25249,11 @@ const BASE_CONFIG = {
|
|
|
25249
25249
|
apiBaseUrl: _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_BASE_API_URL,
|
|
25250
25250
|
exporterEndpoint: _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
|
|
25251
25251
|
recordCanvas: false,
|
|
25252
|
-
|
|
25253
|
-
|
|
25252
|
+
// Off by default: inlining reads pixels via canvas and requires CORS on cross-origin hosts (e.g. S3).
|
|
25253
|
+
// Set true when asset URLs send Access-Control-Allow-Origin for your app origin.
|
|
25254
|
+
inlineImages: false,
|
|
25255
|
+
// Off by default: inlining fetches stylesheet text; cross-origin <link> assets need CORS when enabled.
|
|
25256
|
+
inlineStylesheet: false,
|
|
25254
25257
|
recordNavigation: true,
|
|
25255
25258
|
schemifyDocSpanPayload: true,
|
|
25256
25259
|
ignoreUrls: [],
|
|
@@ -25263,7 +25266,7 @@ const BASE_CONFIG = {
|
|
|
25263
25266
|
widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
|
|
25264
25267
|
useWebsocket: true,
|
|
25265
25268
|
buffering: {
|
|
25266
|
-
enabled:
|
|
25269
|
+
enabled: true,
|
|
25267
25270
|
windowMinutes: 0.5,
|
|
25268
25271
|
snapshotIntervalMs: 20000,
|
|
25269
25272
|
},
|
|
@@ -26904,6 +26907,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26904
26907
|
|
|
26905
26908
|
class RecorderBrowserSDK {
|
|
26906
26909
|
constructor() {
|
|
26910
|
+
this.generation = 0;
|
|
26907
26911
|
this.intervals = {
|
|
26908
26912
|
restart: null,
|
|
26909
26913
|
bufferSnapshot: null,
|
|
@@ -26939,12 +26943,15 @@ class RecorderBrowserSDK {
|
|
|
26939
26943
|
throw new Error('Configuration not initialized. Call init() before start().');
|
|
26940
26944
|
}
|
|
26941
26945
|
this.startedAt = new Date().toISOString();
|
|
26946
|
+
const gen = ++this.generation;
|
|
26942
26947
|
this.stopFn = (0,rrweb__WEBPACK_IMPORTED_MODULE_6__.record)({
|
|
26943
26948
|
...this._buildRecordOptions(),
|
|
26944
26949
|
emit: async (event) => {
|
|
26950
|
+
if (gen !== this.generation)
|
|
26951
|
+
return;
|
|
26945
26952
|
const ts = event.timestamp;
|
|
26946
26953
|
if (!sessionId) {
|
|
26947
|
-
await this._handleBufferOnlyEvent(event, ts);
|
|
26954
|
+
await this._handleBufferOnlyEvent(event, ts, gen);
|
|
26948
26955
|
return;
|
|
26949
26956
|
}
|
|
26950
26957
|
this._handleLiveSessionEvent(event, ts, sessionId, sessionType);
|
|
@@ -26960,6 +26967,7 @@ class RecorderBrowserSDK {
|
|
|
26960
26967
|
var _a;
|
|
26961
26968
|
try {
|
|
26962
26969
|
(_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
26970
|
+
this.stopFn = undefined;
|
|
26963
26971
|
this.start(sessionId, sessionType);
|
|
26964
26972
|
}
|
|
26965
26973
|
catch (_e) {
|
|
@@ -26973,6 +26981,7 @@ class RecorderBrowserSDK {
|
|
|
26973
26981
|
var _a, _b, _c;
|
|
26974
26982
|
(_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
26975
26983
|
this.stopFn = undefined;
|
|
26984
|
+
this.generation++;
|
|
26976
26985
|
if (!((_b = this.config) === null || _b === void 0 ? void 0 : _b.useWebsocket)) {
|
|
26977
26986
|
(_c = this.socketService) === null || _c === void 0 ? void 0 : _c.close();
|
|
26978
26987
|
}
|
|
@@ -27012,13 +27021,15 @@ class RecorderBrowserSDK {
|
|
|
27012
27021
|
* @param event - Event.
|
|
27013
27022
|
* @param ts - Timestamp.
|
|
27014
27023
|
*/
|
|
27015
|
-
async _handleBufferOnlyEvent(event, ts) {
|
|
27024
|
+
async _handleBufferOnlyEvent(event, ts, gen) {
|
|
27016
27025
|
if (!this.crashBuffer)
|
|
27017
27026
|
return;
|
|
27018
27027
|
try {
|
|
27019
27028
|
this._applyConsoleMasking(event);
|
|
27020
27029
|
const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
|
|
27021
27030
|
this.stoppedAt = new Date(ts).toISOString();
|
|
27031
|
+
if (gen !== this.generation)
|
|
27032
|
+
return;
|
|
27022
27033
|
await this.crashBuffer.appendEvent({
|
|
27023
27034
|
ts,
|
|
27024
27035
|
isFullSnapshot: event.type === _rrweb_types__WEBPACK_IMPORTED_MODULE_1__.EventType.FullSnapshot,
|
|
@@ -27292,10 +27303,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
27292
27303
|
|
|
27293
27304
|
|
|
27294
27305
|
class CrashBufferService {
|
|
27295
|
-
constructor(db, tabId, windowMs) {
|
|
27306
|
+
constructor(db, tabId, windowMs, ready = Promise.resolve()) {
|
|
27296
27307
|
this.db = db;
|
|
27297
27308
|
this.tabId = tabId;
|
|
27298
27309
|
this.windowMs = windowMs;
|
|
27310
|
+
this.ready = ready;
|
|
27299
27311
|
this.lastPruneAt = 0;
|
|
27300
27312
|
this.pruneInFlight = null;
|
|
27301
27313
|
this.isActive = true;
|
|
@@ -27318,6 +27330,7 @@ class CrashBufferService {
|
|
|
27318
27330
|
if (!this.isActive)
|
|
27319
27331
|
return;
|
|
27320
27332
|
const isFullSnapshot = Boolean(payload.isFullSnapshot);
|
|
27333
|
+
await this.ready;
|
|
27321
27334
|
await this._safe(async () => {
|
|
27322
27335
|
await this.db.appendEvent({
|
|
27323
27336
|
tabId: this.tabId,
|
|
@@ -27338,6 +27351,7 @@ class CrashBufferService {
|
|
|
27338
27351
|
if (!this.isActive)
|
|
27339
27352
|
return;
|
|
27340
27353
|
let errorEvent = null;
|
|
27354
|
+
await this.ready;
|
|
27341
27355
|
await this._safe(async () => {
|
|
27342
27356
|
const records = payload.map((p) => {
|
|
27343
27357
|
var _a, _b;
|
|
@@ -27386,6 +27400,7 @@ class CrashBufferService {
|
|
|
27386
27400
|
}
|
|
27387
27401
|
async snapshot(_windowMs, now = Date.now()) {
|
|
27388
27402
|
var _a, _b;
|
|
27403
|
+
await this.ready;
|
|
27389
27404
|
const stoppedAt = now;
|
|
27390
27405
|
const startedAt = Math.max(0, stoppedAt - this.windowMs);
|
|
27391
27406
|
// Always include a full snapshot "anchor" if one exists at/before the window start.
|
|
@@ -28026,6 +28041,8 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
|
|
|
28026
28041
|
this.sessionId = null;
|
|
28027
28042
|
this.usePostMessage = false;
|
|
28028
28043
|
this.isInitialized = false;
|
|
28044
|
+
this.lastUserPayload = null;
|
|
28045
|
+
this.lastSubscribeSession = null;
|
|
28029
28046
|
this.options = {
|
|
28030
28047
|
apiKey: '',
|
|
28031
28048
|
socketUrl: '',
|
|
@@ -28088,6 +28105,15 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
|
|
|
28088
28105
|
this.isConnecting = false;
|
|
28089
28106
|
this.isConnected = true;
|
|
28090
28107
|
this.usePostMessage = false;
|
|
28108
|
+
// Re-establish identity and session on every (re)connect: socket.io's auto-reconnect
|
|
28109
|
+
// fires 'ready' again after a drop, but the server has no memory of the previous
|
|
28110
|
+
// setUser/subscribe calls — the client must replay them.
|
|
28111
|
+
if (this.lastUserPayload && this.socket) {
|
|
28112
|
+
this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, this.lastUserPayload);
|
|
28113
|
+
}
|
|
28114
|
+
if (this.lastSubscribeSession) {
|
|
28115
|
+
this._emitSubscribe(this.lastSubscribeSession);
|
|
28116
|
+
}
|
|
28091
28117
|
this.flushQueue();
|
|
28092
28118
|
});
|
|
28093
28119
|
this.socket.on('disconnect', (err) => {
|
|
@@ -28154,16 +28180,33 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
|
|
|
28154
28180
|
this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_ADD_EVENT, event);
|
|
28155
28181
|
}
|
|
28156
28182
|
subscribeToSession(session) {
|
|
28183
|
+
// Remember the session so reconnects replay subscribe + started.
|
|
28184
|
+
this.lastSubscribeSession = session;
|
|
28185
|
+
this._emitSubscribe(session);
|
|
28186
|
+
}
|
|
28187
|
+
_emitSubscribe(session) {
|
|
28157
28188
|
this.sessionId = session.shortId || session._id;
|
|
28158
|
-
const
|
|
28189
|
+
const subscribePayload = {
|
|
28159
28190
|
projectId: session.project,
|
|
28160
28191
|
workspaceId: session.workspace,
|
|
28161
28192
|
debugSessionId: this.sessionId,
|
|
28162
28193
|
sessionType: session.creationType,
|
|
28163
28194
|
};
|
|
28164
|
-
|
|
28165
|
-
//
|
|
28166
|
-
|
|
28195
|
+
const startedPayload = { debugSessionId: session._id };
|
|
28196
|
+
// Send directly (not via the queue). The queue would cause a duplicate emit on
|
|
28197
|
+
// the next 'ready' alongside the replay, since 'ready' also replays lastSubscribeSession.
|
|
28198
|
+
if (this.usePostMessage) {
|
|
28199
|
+
this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SUBSCRIBE_EVENT, subscribePayload);
|
|
28200
|
+
this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STARTED_EVENT, startedPayload);
|
|
28201
|
+
}
|
|
28202
|
+
else if (this.socket && this.isConnected) {
|
|
28203
|
+
this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_SUBSCRIBE_EVENT, subscribePayload);
|
|
28204
|
+
this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STARTED_EVENT, startedPayload);
|
|
28205
|
+
}
|
|
28206
|
+
else {
|
|
28207
|
+
// Not connected: 'ready' will replay via lastSubscribeSession once the socket is up.
|
|
28208
|
+
this._initConnection();
|
|
28209
|
+
}
|
|
28167
28210
|
}
|
|
28168
28211
|
unsubscribeFromSession(stopSession) {
|
|
28169
28212
|
if (this.sessionId) {
|
|
@@ -28172,9 +28215,23 @@ class SocketService extends lib0_observable__WEBPACK_IMPORTED_MODULE_4__.Observa
|
|
|
28172
28215
|
this.emitSocketEvent(_config__WEBPACK_IMPORTED_MODULE_2__.SESSION_STOPPED_EVENT, {});
|
|
28173
28216
|
}
|
|
28174
28217
|
}
|
|
28218
|
+
this.lastSubscribeSession = null;
|
|
28175
28219
|
}
|
|
28176
28220
|
setUser(data) {
|
|
28177
|
-
|
|
28221
|
+
// Remember the last identity so 'ready' (initial connect + every reconnect) can replay it.
|
|
28222
|
+
// Send directly here rather than queuing: the queue would cause a duplicate emit on the
|
|
28223
|
+
// next 'ready' alongside the replay.
|
|
28224
|
+
this.lastUserPayload = data;
|
|
28225
|
+
if (this.usePostMessage) {
|
|
28226
|
+
this.sendViaPostMessage(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, data);
|
|
28227
|
+
}
|
|
28228
|
+
else if (this.socket && this.isConnected) {
|
|
28229
|
+
this.socket.emit(_config__WEBPACK_IMPORTED_MODULE_2__.SOCKET_SET_USER_EVENT, data);
|
|
28230
|
+
}
|
|
28231
|
+
else {
|
|
28232
|
+
// Not connected yet: 'ready' will replay lastUserPayload once the socket is up.
|
|
28233
|
+
this._initConnection();
|
|
28234
|
+
}
|
|
28178
28235
|
}
|
|
28179
28236
|
close() {
|
|
28180
28237
|
return new Promise((resolve) => {
|
|
@@ -28417,13 +28474,11 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28417
28474
|
this._start();
|
|
28418
28475
|
}
|
|
28419
28476
|
else {
|
|
28420
|
-
// Buffer-only recording when there is no active debug session.
|
|
28421
28477
|
this._startBufferOnlyRecording();
|
|
28422
28478
|
}
|
|
28423
28479
|
this._registerWidgetEvents();
|
|
28424
28480
|
this._registerSocketServiceListeners();
|
|
28425
28481
|
_services_messaging_service__WEBPACK_IMPORTED_MODULE_9__["default"].sendMessage('state-change', this.sessionState);
|
|
28426
|
-
// Emit init observable event
|
|
28427
28482
|
this.emit('init', [this]);
|
|
28428
28483
|
}
|
|
28429
28484
|
_setupCrashBuffer() {
|
|
@@ -28431,7 +28486,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28431
28486
|
if ((_a = this._configs.buffering) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
28432
28487
|
const windowMinutes = this._configs.buffering.windowMinutes || 0.5;
|
|
28433
28488
|
const windowMs = Math.max(10000, windowMinutes * 60 * 1000);
|
|
28434
|
-
|
|
28489
|
+
const ready = this._bufferDb.clearTab(this._tabId).catch(() => undefined);
|
|
28490
|
+
this._crashBuffer = new _services_crashBuffer_service__WEBPACK_IMPORTED_MODULE_13__.CrashBufferService(this._bufferDb, this._tabId, windowMs, ready);
|
|
28435
28491
|
this._recorder.setCrashBuffer(this._crashBuffer);
|
|
28436
28492
|
this._tracer.setCrashBuffer(this._crashBuffer);
|
|
28437
28493
|
this._crashBuffer.on('error-span-appended', (payload) => {
|
|
@@ -28483,10 +28539,14 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28483
28539
|
}
|
|
28484
28540
|
_startBufferOnlyRecording() {
|
|
28485
28541
|
var _a, _b;
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28489
|
-
|
|
28542
|
+
// NOTE: `this.sessionId` is intentionally NOT checked. `_stop()` runs
|
|
28543
|
+
// before `_clearSession()` (the stopSession API call sits between them),
|
|
28544
|
+
// so the clear().then() chain fires while sessionId is still set.
|
|
28545
|
+
// Bailing on sessionId here meant rrweb never restarted after manual
|
|
28546
|
+
// stop, leaving the buffer with no FullSnapshot and silently breaking
|
|
28547
|
+
// exception-triggered flushBuffer. `_recorder.restart(null, ...)` passes
|
|
28548
|
+
// null explicitly, so it's safe regardless of `this.sessionId`.
|
|
28549
|
+
if (!this._crashBuffer || !((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled) || this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
|
|
28490
28550
|
return;
|
|
28491
28551
|
}
|
|
28492
28552
|
void this._recorder.restart(null, _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL);
|
|
@@ -28556,9 +28616,10 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28556
28616
|
async stop(comment) {
|
|
28557
28617
|
try {
|
|
28558
28618
|
this._checkOperation('stop');
|
|
28619
|
+
const sid = this.sessionId;
|
|
28559
28620
|
this._stop();
|
|
28560
28621
|
if (this.continuousRecording) {
|
|
28561
|
-
await this._apiService.stopContinuousDebugSession(
|
|
28622
|
+
await this._apiService.stopContinuousDebugSession(sid);
|
|
28562
28623
|
this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
|
|
28563
28624
|
}
|
|
28564
28625
|
else {
|
|
@@ -28566,10 +28627,9 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28566
28627
|
sessionAttributes: { comment },
|
|
28567
28628
|
stoppedAt: this._recorder.stoppedAt,
|
|
28568
28629
|
};
|
|
28569
|
-
const response = await this._apiService.stopSession(
|
|
28630
|
+
const response = await this._apiService.stopSession(sid, request);
|
|
28570
28631
|
_eventBus__WEBPACK_IMPORTED_MODULE_7__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_RESPONSE, response);
|
|
28571
28632
|
}
|
|
28572
|
-
this._clearSession();
|
|
28573
28633
|
}
|
|
28574
28634
|
catch (error) {
|
|
28575
28635
|
this.error = error.message;
|
|
@@ -28605,15 +28665,15 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28605
28665
|
async cancel() {
|
|
28606
28666
|
try {
|
|
28607
28667
|
this._checkOperation('cancel');
|
|
28668
|
+
const sid = this.sessionId;
|
|
28608
28669
|
this._stop();
|
|
28609
28670
|
if (this.continuousRecording) {
|
|
28610
|
-
await this._apiService.stopContinuousDebugSession(
|
|
28671
|
+
await this._apiService.stopContinuousDebugSession(sid);
|
|
28611
28672
|
this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
|
|
28612
28673
|
}
|
|
28613
28674
|
else {
|
|
28614
|
-
await this._apiService.cancelSession(
|
|
28675
|
+
await this._apiService.cancelSession(sid);
|
|
28615
28676
|
}
|
|
28616
|
-
this._clearSession();
|
|
28617
28677
|
}
|
|
28618
28678
|
catch (error) {
|
|
28619
28679
|
this.error = error.message;
|
|
@@ -28665,12 +28725,7 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28665
28725
|
}
|
|
28666
28726
|
}
|
|
28667
28727
|
async _flushBuffer(sessionId) {
|
|
28668
|
-
|
|
28669
|
-
if (!sessionId ||
|
|
28670
|
-
!this._crashBuffer ||
|
|
28671
|
-
this._isFlushingBuffer ||
|
|
28672
|
-
!((_b = (_a = this._configs) === null || _a === void 0 ? void 0 : _a.buffering) === null || _b === void 0 ? void 0 : _b.enabled) ||
|
|
28673
|
-
this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped) {
|
|
28728
|
+
if (!sessionId || !this._crashBuffer || this._isFlushingBuffer) {
|
|
28674
28729
|
return null;
|
|
28675
28730
|
}
|
|
28676
28731
|
this._isFlushingBuffer = true;
|
|
@@ -28860,6 +28915,8 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28860
28915
|
});
|
|
28861
28916
|
this._socketService.on(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_SAVE_BUFFER_EVENT, (payload) => {
|
|
28862
28917
|
var _a;
|
|
28918
|
+
if (this.sessionState !== _types__WEBPACK_IMPORTED_MODULE_4__.SessionState.stopped)
|
|
28919
|
+
return;
|
|
28863
28920
|
this._flushBuffer((_a = payload === null || payload === void 0 ? void 0 : payload.debugSession) === null || _a === void 0 ? void 0 : _a._id);
|
|
28864
28921
|
});
|
|
28865
28922
|
}
|
|
@@ -28930,7 +28987,18 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28930
28987
|
this._tracer.stop();
|
|
28931
28988
|
this._recorder.stop();
|
|
28932
28989
|
this._navigationRecorder.stop();
|
|
28933
|
-
|
|
28990
|
+
// Clear session identity synchronously. The buffer-restart chain and the
|
|
28991
|
+
// error-span-appended listener both gate on `this.sessionId === null`;
|
|
28992
|
+
// deferring this to `_clearSession()` (after the network stopSession
|
|
28993
|
+
// call) left them seeing a stale id and silently no-oping. Callers that
|
|
28994
|
+
// need the id for the stop/cancel API must capture it before _stop().
|
|
28995
|
+
this.session = null;
|
|
28996
|
+
this.sessionId = null;
|
|
28997
|
+
// rrweb assigns new node IDs on each record() call, so the next buffer
|
|
28998
|
+
// segment must not carry events from the previous generation. Await the
|
|
28999
|
+
// clear so its IDB tx can't race past the fresh FullSnapshot.
|
|
29000
|
+
const cleared = this._crashBuffer ? this._crashBuffer.clear() : Promise.resolve();
|
|
29001
|
+
void cleared.catch(() => undefined).then(() => this._startBufferOnlyRecording());
|
|
28934
29002
|
}
|
|
28935
29003
|
/**
|
|
28936
29004
|
* Pause the session tracing and recording
|
|
@@ -57765,6 +57833,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
57765
57833
|
/* harmony export */ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX),
|
|
57766
57834
|
/* harmony export */ MULTIPLAYER_TRACE_SESSION_PREFIX: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.MULTIPLAYER_TRACE_SESSION_PREFIX),
|
|
57767
57835
|
/* harmony export */ NavigationRecorder: () => (/* reexport safe */ _navigation__WEBPACK_IMPORTED_MODULE_6__.NavigationRecorder),
|
|
57836
|
+
/* harmony export */ SessionRecorder: () => (/* binding */ SessionRecorderInstance),
|
|
57768
57837
|
/* harmony export */ SessionRecorderBrowserTraceExporter: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderBrowserTraceExporter),
|
|
57769
57838
|
/* harmony export */ SessionRecorderIdGenerator: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderIdGenerator),
|
|
57770
57839
|
/* harmony export */ SessionRecorderSdk: () => (/* reexport safe */ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_7__.SessionRecorderSdk),
|
|
@@ -57812,6 +57881,7 @@ else {
|
|
|
57812
57881
|
SessionRecorderInstance = new _session_recorder__WEBPACK_IMPORTED_MODULE_3__.SessionRecorder();
|
|
57813
57882
|
}
|
|
57814
57883
|
|
|
57884
|
+
|
|
57815
57885
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SessionRecorderInstance);
|
|
57816
57886
|
|
|
57817
57887
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyB,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAIlH,eAAO,MAAM,sBAAsB,EAAE,aASpC,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,yBAuBxC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAyB,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAIlH,eAAO,MAAM,sBAAsB,EAAE,aASpC,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,yBAuBxC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,sBAAsB,CA0CxD,CAAA"}
|
package/dist/config/defaults.js
CHANGED
|
@@ -46,8 +46,11 @@ export const BASE_CONFIG = {
|
|
|
46
46
|
apiBaseUrl: MULTIPLAYER_BASE_API_URL,
|
|
47
47
|
exporterEndpoint: MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
|
|
48
48
|
recordCanvas: false,
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
// Off by default: inlining reads pixels via canvas and requires CORS on cross-origin hosts (e.g. S3).
|
|
50
|
+
// Set true when asset URLs send Access-Control-Allow-Origin for your app origin.
|
|
51
|
+
inlineImages: false,
|
|
52
|
+
// Off by default: inlining fetches stylesheet text; cross-origin <link> assets need CORS when enabled.
|
|
53
|
+
inlineStylesheet: false,
|
|
51
54
|
recordNavigation: true,
|
|
52
55
|
schemifyDocSpanPayload: true,
|
|
53
56
|
ignoreUrls: [],
|
|
@@ -60,7 +63,7 @@ export const BASE_CONFIG = {
|
|
|
60
63
|
widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
|
|
61
64
|
useWebsocket: true,
|
|
62
65
|
buffering: {
|
|
63
|
-
enabled:
|
|
66
|
+
enabled: true,
|
|
64
67
|
windowMinutes: 0.5,
|
|
65
68
|
snapshotIntervalMs: 20000,
|
|
66
69
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,iDAAiD,GAClD,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAyC,qBAAqB,EAA6B,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,0BAA0B,EAAE,uCAAuC,EAAE,MAAM,aAAa,CAAA;AACjG,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,CAAA;AAEtE,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,IAAI;IAC7B,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC;IAC/B,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,eAAe;IACnC,eAAe,EAAE,gBAAgB;IACjC,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,EAAE;CACrB,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAA8B;IACnE,0BAA0B,EAAE,uBAAuB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,gCAAgC,EAAE,kEAAkE;IACpG,mCAAmC,EAAE,kEAAkE;IACvG,wBAAwB,EAAE,sBAAsB;IAChD,wBAAwB,EAAE,iBAAiB;IAC3C,UAAU,EAAE,iBAAiB;IAC7B,gBAAgB,EAAE,0FAA0F;IAC5G,kBAAkB,EAAE,kBAAkB;IACtC,cAAc,EAAE,kBAAkB;IAClC,gBAAgB,EAAE,kBAAkB;IACpC,sBAAsB,EAAE,mCAAmC;IAC3D,4BAA4B,EAC1B,mOAAmO;IACrO,0BAA0B,EAAE,gBAAgB;IAC5C,iBAAiB,EAAE,gBAAgB;IACnC,oBAAoB,EAClB,iJAAiJ;IACnJ,wBAAwB,EAAE,+CAA+C;IACzE,8BAA8B,EAAE,kBAAkB;IAClD,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,QAAQ;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,MAAM,EAAE,EAAE;IAEV,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;IAEf,UAAU,EAAE,IAAI;IAChB,uBAAuB,EAAE,IAAI;IAC7B,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;IAExD,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,wBAAwB;IACpC,gBAAgB,EAAE,iDAAiD;IAEnE,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,iDAAiD,GAClD,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAyC,qBAAqB,EAA6B,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,0BAA0B,EAAE,uCAAuC,EAAE,MAAM,aAAa,CAAA;AACjG,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,CAAA;AAEtE,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,IAAI;IAC7B,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC;IAC/B,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,eAAe;IACnC,eAAe,EAAE,gBAAgB;IACjC,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,EAAE;CACrB,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAA8B;IACnE,0BAA0B,EAAE,uBAAuB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,gCAAgC,EAAE,kEAAkE;IACpG,mCAAmC,EAAE,kEAAkE;IACvG,wBAAwB,EAAE,sBAAsB;IAChD,wBAAwB,EAAE,iBAAiB;IAC3C,UAAU,EAAE,iBAAiB;IAC7B,gBAAgB,EAAE,0FAA0F;IAC5G,kBAAkB,EAAE,kBAAkB;IACtC,cAAc,EAAE,kBAAkB;IAClC,gBAAgB,EAAE,kBAAkB;IACpC,sBAAsB,EAAE,mCAAmC;IAC3D,4BAA4B,EAC1B,mOAAmO;IACrO,0BAA0B,EAAE,gBAAgB;IAC5C,iBAAiB,EAAE,gBAAgB;IACnC,oBAAoB,EAClB,iJAAiJ;IACnJ,wBAAwB,EAAE,+CAA+C;IACzE,8BAA8B,EAAE,kBAAkB;IAClD,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,QAAQ;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,MAAM,EAAE,EAAE;IAEV,OAAO,EAAE,EAAE;IACX,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;IAEf,UAAU,EAAE,IAAI;IAChB,uBAAuB,EAAE,IAAI;IAC7B,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;IAExD,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE,wBAAwB;IACpC,gBAAgB,EAAE,iDAAiD;IAEnE,YAAY,EAAE,KAAK;IACnB,sGAAsG;IACtG,iFAAiF;IACjF,YAAY,EAAE,KAAK;IACnB,uGAAuG;IACvG,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,IAAI;IACtB,sBAAsB,EAAE,IAAI;IAE5B,UAAU,EAAE,EAAE;IACd,4BAA4B,EAAE,EAAE;IAEhC,gBAAgB,EAAE,0BAA0B;IAC5C,2BAA2B,EAAE,uCAAuC;IAEpE,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,OAAO,EAAE,sBAAsB;IAC/B,mBAAmB,EAAE,0BAA0B;IAE/C,YAAY,EAAE,IAAI;IAElB,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,GAAG;QAClB,kBAAkB,EAAE,KAAK;KAC1B;CACF,CAAA"}
|