@multiplayer-app/session-recorder-browser 2.0.38 → 2.0.40
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/dist/browser/index.js +37 -14
- package/dist/exporters/index.js +1 -1
- package/dist/index.js +37 -14
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +37 -14
- 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/session-recorder.d.ts.map +1 -1
- package/dist/session-recorder.js +26 -11
- package/dist/session-recorder.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -24263,7 +24263,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
|
|
|
24263
24263
|
const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
|
|
24264
24264
|
const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
|
|
24265
24265
|
const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
|
|
24266
|
-
const PACKAGE_VERSION_EXPORT = "2.0.
|
|
24266
|
+
const PACKAGE_VERSION_EXPORT = "2.0.40" || 0;
|
|
24267
24267
|
// Regex patterns for OpenTelemetry ignore URLs
|
|
24268
24268
|
const OTEL_IGNORE_URLS = [
|
|
24269
24269
|
// Traces endpoint
|
|
@@ -25951,6 +25951,7 @@ if (typeof XMLHttpRequest !== 'undefined') {
|
|
|
25951
25951
|
|
|
25952
25952
|
class RecorderBrowserSDK {
|
|
25953
25953
|
constructor() {
|
|
25954
|
+
this.generation = 0;
|
|
25954
25955
|
this.intervals = {
|
|
25955
25956
|
restart: null,
|
|
25956
25957
|
bufferSnapshot: null,
|
|
@@ -25986,12 +25987,15 @@ class RecorderBrowserSDK {
|
|
|
25986
25987
|
throw new Error('Configuration not initialized. Call init() before start().');
|
|
25987
25988
|
}
|
|
25988
25989
|
this.startedAt = new Date().toISOString();
|
|
25990
|
+
const gen = ++this.generation;
|
|
25989
25991
|
this.stopFn = (0,rrweb__WEBPACK_IMPORTED_MODULE_6__.record)({
|
|
25990
25992
|
...this._buildRecordOptions(),
|
|
25991
25993
|
emit: async (event) => {
|
|
25994
|
+
if (gen !== this.generation)
|
|
25995
|
+
return;
|
|
25992
25996
|
const ts = event.timestamp;
|
|
25993
25997
|
if (!sessionId) {
|
|
25994
|
-
await this._handleBufferOnlyEvent(event, ts);
|
|
25998
|
+
await this._handleBufferOnlyEvent(event, ts, gen);
|
|
25995
25999
|
return;
|
|
25996
26000
|
}
|
|
25997
26001
|
this._handleLiveSessionEvent(event, ts, sessionId, sessionType);
|
|
@@ -26007,6 +26011,7 @@ class RecorderBrowserSDK {
|
|
|
26007
26011
|
var _a;
|
|
26008
26012
|
try {
|
|
26009
26013
|
(_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
26014
|
+
this.stopFn = undefined;
|
|
26010
26015
|
this.start(sessionId, sessionType);
|
|
26011
26016
|
}
|
|
26012
26017
|
catch (_e) {
|
|
@@ -26020,6 +26025,7 @@ class RecorderBrowserSDK {
|
|
|
26020
26025
|
var _a, _b, _c;
|
|
26021
26026
|
(_a = this.stopFn) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
26022
26027
|
this.stopFn = undefined;
|
|
26028
|
+
this.generation++;
|
|
26023
26029
|
if (!((_b = this.config) === null || _b === void 0 ? void 0 : _b.useWebsocket)) {
|
|
26024
26030
|
(_c = this.socketService) === null || _c === void 0 ? void 0 : _c.close();
|
|
26025
26031
|
}
|
|
@@ -26059,13 +26065,15 @@ class RecorderBrowserSDK {
|
|
|
26059
26065
|
* @param event - Event.
|
|
26060
26066
|
* @param ts - Timestamp.
|
|
26061
26067
|
*/
|
|
26062
|
-
async _handleBufferOnlyEvent(event, ts) {
|
|
26068
|
+
async _handleBufferOnlyEvent(event, ts, gen) {
|
|
26063
26069
|
if (!this.crashBuffer)
|
|
26064
26070
|
return;
|
|
26065
26071
|
try {
|
|
26066
26072
|
this._applyConsoleMasking(event);
|
|
26067
26073
|
const packedEvent = (0,_rrweb_packer__WEBPACK_IMPORTED_MODULE_0__.pack)(event);
|
|
26068
26074
|
this.stoppedAt = new Date(ts).toISOString();
|
|
26075
|
+
if (gen !== this.generation)
|
|
26076
|
+
return;
|
|
26069
26077
|
await this.crashBuffer.appendEvent({
|
|
26070
26078
|
ts,
|
|
26071
26079
|
isFullSnapshot: event.type === _rrweb_types__WEBPACK_IMPORTED_MODULE_1__.EventType.FullSnapshot,
|
|
@@ -27563,10 +27571,14 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
27563
27571
|
}
|
|
27564
27572
|
_startBufferOnlyRecording() {
|
|
27565
27573
|
var _a, _b;
|
|
27566
|
-
|
|
27567
|
-
|
|
27568
|
-
|
|
27569
|
-
|
|
27574
|
+
// NOTE: `this.sessionId` is intentionally NOT checked. `_stop()` runs
|
|
27575
|
+
// before `_clearSession()` (the stopSession API call sits between them),
|
|
27576
|
+
// so the clear().then() chain fires while sessionId is still set.
|
|
27577
|
+
// Bailing on sessionId here meant rrweb never restarted after manual
|
|
27578
|
+
// stop, leaving the buffer with no FullSnapshot and silently breaking
|
|
27579
|
+
// exception-triggered flushBuffer. `_recorder.restart(null, ...)` passes
|
|
27580
|
+
// null explicitly, so it's safe regardless of `this.sessionId`.
|
|
27581
|
+
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) {
|
|
27570
27582
|
return;
|
|
27571
27583
|
}
|
|
27572
27584
|
void this._recorder.restart(null, _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL);
|
|
@@ -27636,9 +27648,10 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
27636
27648
|
async stop(comment) {
|
|
27637
27649
|
try {
|
|
27638
27650
|
this._checkOperation('stop');
|
|
27651
|
+
const sid = this.sessionId;
|
|
27639
27652
|
this._stop();
|
|
27640
27653
|
if (this.continuousRecording) {
|
|
27641
|
-
await this._apiService.stopContinuousDebugSession(
|
|
27654
|
+
await this._apiService.stopContinuousDebugSession(sid);
|
|
27642
27655
|
this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
|
|
27643
27656
|
}
|
|
27644
27657
|
else {
|
|
@@ -27646,10 +27659,9 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
27646
27659
|
sessionAttributes: { comment },
|
|
27647
27660
|
stoppedAt: this._recorder.stoppedAt,
|
|
27648
27661
|
};
|
|
27649
|
-
const response = await this._apiService.stopSession(
|
|
27662
|
+
const response = await this._apiService.stopSession(sid, request);
|
|
27650
27663
|
_eventBus__WEBPACK_IMPORTED_MODULE_7__.recorderEventBus.emit(_config__WEBPACK_IMPORTED_MODULE_5__.SESSION_RESPONSE, response);
|
|
27651
27664
|
}
|
|
27652
|
-
this._clearSession();
|
|
27653
27665
|
}
|
|
27654
27666
|
catch (error) {
|
|
27655
27667
|
this.error = error.message;
|
|
@@ -27685,15 +27697,15 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
27685
27697
|
async cancel() {
|
|
27686
27698
|
try {
|
|
27687
27699
|
this._checkOperation('cancel');
|
|
27700
|
+
const sid = this.sessionId;
|
|
27688
27701
|
this._stop();
|
|
27689
27702
|
if (this.continuousRecording) {
|
|
27690
|
-
await this._apiService.stopContinuousDebugSession(
|
|
27703
|
+
await this._apiService.stopContinuousDebugSession(sid);
|
|
27691
27704
|
this.sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
|
|
27692
27705
|
}
|
|
27693
27706
|
else {
|
|
27694
|
-
await this._apiService.cancelSession(
|
|
27707
|
+
await this._apiService.cancelSession(sid);
|
|
27695
27708
|
}
|
|
27696
|
-
this._clearSession();
|
|
27697
27709
|
}
|
|
27698
27710
|
catch (error) {
|
|
27699
27711
|
this.error = error.message;
|
|
@@ -28007,7 +28019,18 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_16__.Obse
|
|
|
28007
28019
|
this._tracer.stop();
|
|
28008
28020
|
this._recorder.stop();
|
|
28009
28021
|
this._navigationRecorder.stop();
|
|
28010
|
-
|
|
28022
|
+
// Clear session identity synchronously. The buffer-restart chain and the
|
|
28023
|
+
// error-span-appended listener both gate on `this.sessionId === null`;
|
|
28024
|
+
// deferring this to `_clearSession()` (after the network stopSession
|
|
28025
|
+
// call) left them seeing a stale id and silently no-oping. Callers that
|
|
28026
|
+
// need the id for the stop/cancel API must capture it before _stop().
|
|
28027
|
+
this.session = null;
|
|
28028
|
+
this.sessionId = null;
|
|
28029
|
+
// rrweb assigns new node IDs on each record() call, so the next buffer
|
|
28030
|
+
// segment must not carry events from the previous generation. Await the
|
|
28031
|
+
// clear so its IDB tx can't race past the fresh FullSnapshot.
|
|
28032
|
+
const cleared = this._crashBuffer ? this._crashBuffer.clear() : Promise.resolve();
|
|
28033
|
+
void cleared.catch(() => undefined).then(() => this._startBufferOnlyRecording());
|
|
28011
28034
|
}
|
|
28012
28035
|
/**
|
|
28013
28036
|
* Pause the session tracing and recording
|