@multiplayer-app/session-recorder-browser 1.3.22 → 1.3.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 CHANGED
@@ -114,6 +114,14 @@ SessionRecorder.init({
114
114
  // should be sent through `exporters`
115
115
  sampleTraceRatio: 0,
116
116
 
117
+ // crash buffer: keep a rolling window of rrweb + traces when no recording is active.
118
+ // when user starts a session or saves (e.g. on error), the buffer is flushed into the session.
119
+ buffering: {
120
+ enabled: true, // enable/disable buffering (default: true)
121
+ windowMinutes: 1, // rolling window size in minutes (default: 1)
122
+ snapshotIntervalMs: 30000 // full snapshot interval while buffering in ms (default: 30000)
123
+ },
124
+
117
125
  // optional: exporters allow you to send
118
126
  // OTLP data to observability platforms
119
127
  exporters: [
@@ -25054,7 +25054,7 @@ const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
25054
25054
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
25055
25055
  const REMOTE_SESSION_RECORDING_START = 'remote-session-recording:start';
25056
25056
  const REMOTE_SESSION_RECORDING_STOP = 'remote-session-recording:stop';
25057
- const PACKAGE_VERSION_EXPORT = "1.3.22" || 0;
25057
+ const PACKAGE_VERSION_EXPORT = "1.3.24" || 0;
25058
25058
  // Regex patterns for OpenTelemetry ignore URLs
25059
25059
  const OTEL_IGNORE_URLS = [
25060
25060
  // Traces endpoint
@@ -25779,8 +25779,8 @@ class CrashBufferSpanProcessor {
25779
25779
  this._crashBuffer.appendSpans([
25780
25780
  {
25781
25781
  ts: span.startTime[0] * 1000 + span.startTime[1] / 1000000,
25782
- span: this._serializeSpan(span)
25783
- }
25782
+ span: this._serializeSpan(span),
25783
+ },
25784
25784
  ]);
25785
25785
  }
25786
25786
  return;
@@ -26063,13 +26063,14 @@ __webpack_require__.r(__webpack_exports__);
26063
26063
 
26064
26064
 
26065
26065
 
26066
+ const clientIdGenerator = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderSdk.getIdGenerator(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH);
26066
26067
  class TracerBrowserSDK {
26067
26068
  constructor() {
26068
26069
  this.clientId = '';
26069
26070
  this.sessionId = '';
26070
26071
  this.globalErrorListenersRegistered = false;
26071
26072
  }
26072
- setSessionId(sessionId, sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL) {
26073
+ _setSessionId(sessionId, sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.MANUAL) {
26073
26074
  this.sessionId = sessionId;
26074
26075
  if (!this.idGenerator) {
26075
26076
  throw new Error('Id generator not initialized');
@@ -26078,32 +26079,32 @@ class TracerBrowserSDK {
26078
26079
  }
26079
26080
  init(options) {
26080
26081
  this.config = options;
26081
- this.clientId = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderSdk.getIdGenerator(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.MULTIPLAYER_TRACE_CLIENT_ID_LENGTH)();
26082
+ this.clientId = clientIdGenerator();
26082
26083
  const { application, version, environment } = this.config;
26083
26084
  this.idGenerator = new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderIdGenerator();
26084
- this.setSessionId('', _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.SESSION_CACHE);
26085
+ this._setSessionId('', _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.SESSION_CACHE);
26085
26086
  this.exporter = new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderBrowserTraceExporter({
26086
26087
  apiKey: options.apiKey,
26087
26088
  url: (0,_helpers__WEBPACK_IMPORTED_MODULE_3__.getExporterEndpoint)(options.exporterEndpoint),
26088
- usePostMessageFallback: options.usePostMessageFallback
26089
+ usePostMessageFallback: options.usePostMessageFallback,
26089
26090
  });
26090
26091
  this.batchSpanProcessor = new _opentelemetry_sdk_trace_base__WEBPACK_IMPORTED_MODULE_5__.BatchSpanProcessor(this.exporter);
26091
26092
  this.tracerProvider = new _opentelemetry_sdk_trace_web__WEBPACK_IMPORTED_MODULE_6__.WebTracerProvider({
26092
26093
  resource: (0,_opentelemetry_resources__WEBPACK_IMPORTED_MODULE_7__.resourceFromAttributes)({
26093
26094
  [_opentelemetry_semantic_conventions__WEBPACK_IMPORTED_MODULE_8__.SEMRESATTRS_SERVICE_NAME]: application,
26094
26095
  [_opentelemetry_semantic_conventions__WEBPACK_IMPORTED_MODULE_8__.SEMRESATTRS_SERVICE_VERSION]: version,
26095
- [_opentelemetry_semantic_conventions__WEBPACK_IMPORTED_MODULE_8__.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: environment
26096
+ [_opentelemetry_semantic_conventions__WEBPACK_IMPORTED_MODULE_8__.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: environment,
26096
26097
  }),
26097
26098
  idGenerator: this.idGenerator,
26098
26099
  sampler: new _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderTraceIdRatioBasedSampler(this.config.sampleTraceRatio),
26099
26100
  spanProcessors: [
26100
26101
  this._getSpanSessionIdProcessor(),
26101
- new _CrashBufferSpanProcessor__WEBPACK_IMPORTED_MODULE_4__.CrashBufferSpanProcessor(this.batchSpanProcessor, this.crashBuffer, this.exporter.serializeSpan.bind(this.exporter))
26102
- ]
26102
+ new _CrashBufferSpanProcessor__WEBPACK_IMPORTED_MODULE_4__.CrashBufferSpanProcessor(this.batchSpanProcessor, this.crashBuffer, this.exporter.serializeSpan.bind(this.exporter)),
26103
+ ],
26103
26104
  });
26104
26105
  this.tracerProvider.register({
26105
26106
  // contextManager: new ZoneContextManager(),
26106
- propagator: new _opentelemetry_core__WEBPACK_IMPORTED_MODULE_9__.W3CTraceContextPropagator()
26107
+ propagator: new _opentelemetry_core__WEBPACK_IMPORTED_MODULE_9__.W3CTraceContextPropagator(),
26107
26108
  });
26108
26109
  (0,_opentelemetry_instrumentation__WEBPACK_IMPORTED_MODULE_10__.registerInstrumentations)({
26109
26110
  tracerProvider: this.tracerProvider,
@@ -26131,7 +26132,7 @@ class TracerBrowserSDK {
26131
26132
  requestBody,
26132
26133
  responseBody,
26133
26134
  requestHeaders,
26134
- responseHeaders
26135
+ responseHeaders,
26135
26136
  };
26136
26137
  (0,_helpers__WEBPACK_IMPORTED_MODULE_3__.processHttpPayload)(payload, this.config, span);
26137
26138
  }
@@ -26139,7 +26140,7 @@ class TracerBrowserSDK {
26139
26140
  // eslint-disable-next-line
26140
26141
  console.error('[MULTIPLAYER_SESSION_RECORDER] Failed to capture xml-http payload', error);
26141
26142
  }
26142
- }
26143
+ },
26143
26144
  },
26144
26145
  '@opentelemetry/instrumentation-fetch': {
26145
26146
  clearTimingResources: true,
@@ -26180,7 +26181,7 @@ class TracerBrowserSDK {
26180
26181
  requestBody,
26181
26182
  responseBody,
26182
26183
  requestHeaders,
26183
- responseHeaders
26184
+ responseHeaders,
26184
26185
  };
26185
26186
  (0,_helpers__WEBPACK_IMPORTED_MODULE_3__.processHttpPayload)(payload, this.config, span);
26186
26187
  }
@@ -26188,7 +26189,7 @@ class TracerBrowserSDK {
26188
26189
  // eslint-disable-next-line
26189
26190
  console.error('[MULTIPLAYER_SESSION_RECORDER] Failed to capture fetch payload', error);
26190
26191
  }
26191
- }
26192
+ },
26192
26193
  },
26193
26194
  '@opentelemetry/instrumentation-user-interaction': {
26194
26195
  shouldPreventSpanCreation: (_event, element, span) => {
@@ -26201,10 +26202,10 @@ class TracerBrowserSDK {
26201
26202
  span.setAttribute(`target.attribute.${attribute.name}`, attribute.value);
26202
26203
  });
26203
26204
  return false;
26204
- }
26205
- }
26206
- })
26207
- ]
26205
+ },
26206
+ },
26207
+ }),
26208
+ ],
26208
26209
  });
26209
26210
  this._registerGlobalErrorListeners();
26210
26211
  }
@@ -26215,13 +26216,13 @@ class TracerBrowserSDK {
26215
26216
  if (!this.tracerProvider) {
26216
26217
  throw new Error('Configuration not initialized. Call init() before start().');
26217
26218
  }
26218
- this.setSessionId(sessionId, sessionType);
26219
+ this._setSessionId(sessionId, sessionType);
26219
26220
  }
26220
26221
  stop() {
26221
26222
  if (!this.tracerProvider) {
26222
26223
  throw new Error('Configuration not initialized. Call init() before start().');
26223
26224
  }
26224
- this.setSessionId('', _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.SESSION_CACHE);
26225
+ this._setSessionId('', _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.SESSION_CACHE);
26225
26226
  }
26226
26227
  setApiKey(apiKey) {
26227
26228
  if (!this.exporter) {
@@ -26229,6 +26230,14 @@ class TracerBrowserSDK {
26229
26230
  }
26230
26231
  this.exporter.setApiKey(apiKey);
26231
26232
  }
26233
+ async exportTraces(spans) {
26234
+ var _a;
26235
+ if ((_a = this === null || this === void 0 ? void 0 : this.batchSpanProcessor) === null || _a === void 0 ? void 0 : _a.onEnd) {
26236
+ spans.map((span) => { var _a; return (_a = this === null || this === void 0 ? void 0 : this.batchSpanProcessor) === null || _a === void 0 ? void 0 : _a.onEnd(span); });
26237
+ // return this.batchSpanProcessor.onEnd()
26238
+ }
26239
+ throw new Error('Buffer span processor not initialized');
26240
+ }
26232
26241
  /**
26233
26242
  * Capture an exception as an error span/event.
26234
26243
  * If there is an active span, the exception will be recorded on it.
@@ -26260,14 +26269,6 @@ class TracerBrowserSDK {
26260
26269
  }
26261
26270
  catch (_ignored) { }
26262
26271
  }
26263
- async exportTraces(spans) {
26264
- var _a;
26265
- if ((_a = this === null || this === void 0 ? void 0 : this.batchSpanProcessor) === null || _a === void 0 ? void 0 : _a.onEnd) {
26266
- spans.map((span) => { var _a; return (_a = this === null || this === void 0 ? void 0 : this.batchSpanProcessor) === null || _a === void 0 ? void 0 : _a.onEnd(span); });
26267
- // return this.batchSpanProcessor.onEnd()
26268
- }
26269
- throw new Error('Buffer span processor not initialized');
26270
- }
26271
26272
  _recordException(span, error, errorInfo) {
26272
26273
  span.recordException(error);
26273
26274
  span.setStatus({ code: _opentelemetry_api__WEBPACK_IMPORTED_MODULE_13__.SpanStatusCode.ERROR, message: error.message });
@@ -26290,7 +26291,7 @@ class TracerBrowserSDK {
26290
26291
  if ((_a = this.sessionId) === null || _a === void 0 ? void 0 : _a.length) {
26291
26292
  span.setAttribute(_multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.ATTR_MULTIPLAYER_SESSION_ID, this.sessionId);
26292
26293
  }
26293
- }
26294
+ },
26294
26295
  };
26295
26296
  }
26296
26297
  _registerGlobalErrorListeners() {
@@ -26759,7 +26760,7 @@ class RecorderBrowserSDK {
26759
26760
  constructor() {
26760
26761
  this.intervals = {
26761
26762
  restart: null,
26762
- bufferSnapshot: null
26763
+ bufferSnapshot: null,
26763
26764
  };
26764
26765
  this.startedAt = '';
26765
26766
  this.stoppedAt = '';
@@ -26801,7 +26802,7 @@ class RecorderBrowserSDK {
26801
26802
  return;
26802
26803
  }
26803
26804
  this._handleLiveSessionEvent(event, ts, sessionId, sessionType);
26804
- }
26805
+ },
26805
26806
  });
26806
26807
  this.takeFullSnapshot();
26807
26808
  this._setupPeriodicSnapshots(sessionId, sessionType);
@@ -26878,8 +26879,8 @@ class RecorderBrowserSDK {
26878
26879
  event: {
26879
26880
  event: packedEvent,
26880
26881
  eventType: event.type,
26881
- timestamp: ts
26882
- }
26882
+ timestamp: ts,
26883
+ },
26883
26884
  });
26884
26885
  }
26885
26886
  catch (error) {
@@ -26904,7 +26905,7 @@ class RecorderBrowserSDK {
26904
26905
  eventType: event.type,
26905
26906
  timestamp: ts,
26906
26907
  debugSessionId: sessionId,
26907
- debugSessionType: sessionType
26908
+ debugSessionType: sessionType,
26908
26909
  });
26909
26910
  }
26910
26911
  /**
@@ -26918,7 +26919,7 @@ class RecorderBrowserSDK {
26918
26919
  sampling: { canvas: 5 },
26919
26920
  recordCanvas: (_c = this.config) === null || _c === void 0 ? void 0 : _c.recordCanvas,
26920
26921
  dataURLOptions: { type: 'image/webp', quality: 0.1 },
26921
- plugins: [(0,_rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_3__.getRecordConsolePlugin)({ level: ['log', 'error'] })]
26922
+ plugins: [(0,_rrweb_rrweb_plugin_console_record__WEBPACK_IMPORTED_MODULE_3__.getRecordConsolePlugin)({ level: ['log', 'error'] })],
26922
26923
  };
26923
26924
  if (maskingConfig.maskInputOptions) {
26924
26925
  options.maskInputOptions = maskingConfig.maskInputOptions;
@@ -26980,7 +26981,7 @@ class ApiService {
26980
26981
  this.config = {
26981
26982
  apiKey: '',
26982
26983
  apiBaseUrl: '',
26983
- exporterEndpoint: ''
26984
+ exporterEndpoint: '',
26984
26985
  };
26985
26986
  }
26986
26987
  /**
@@ -26990,7 +26991,7 @@ class ApiService {
26990
26991
  init(config) {
26991
26992
  this.config = {
26992
26993
  ...this.config,
26993
- ...config
26994
+ ...config,
26994
26995
  };
26995
26996
  }
26996
26997
  /**
@@ -27084,14 +27085,14 @@ class ApiService {
27084
27085
  body: body ? JSON.stringify(body) : null,
27085
27086
  headers: {
27086
27087
  'Content-Type': 'application/json',
27087
- ...(this.config.apiKey && { 'X-Api-Key': this.config.apiKey })
27088
- }
27088
+ ...(this.config.apiKey && { 'X-Api-Key': this.config.apiKey }),
27089
+ },
27089
27090
  };
27090
27091
  try {
27091
27092
  const response = await fetch(url, {
27092
27093
  ...params,
27093
27094
  credentials: 'include',
27094
- signal
27095
+ signal,
27095
27096
  });
27096
27097
  if (!response.ok) {
27097
27098
  throw new Error('Network response was not ok: ' + response.statusText);
@@ -27166,7 +27167,7 @@ class CrashBufferService {
27166
27167
  await this._safe(async () => {
27167
27168
  await this.db.setAttrs({
27168
27169
  tabId: this.tabId,
27169
- ...attrs
27170
+ ...attrs,
27170
27171
  });
27171
27172
  }, undefined);
27172
27173
  }
@@ -27184,7 +27185,7 @@ class CrashBufferService {
27184
27185
  tabId: this.tabId,
27185
27186
  ts: payload.ts,
27186
27187
  isFullSnapshot: payload.isFullSnapshot,
27187
- event: payload.event
27188
+ event: payload.event,
27188
27189
  });
27189
27190
  }, undefined);
27190
27191
  if (isFullSnapshot && this.requiresFullSnapshot) {
@@ -27214,7 +27215,7 @@ class CrashBufferService {
27214
27215
  return {
27215
27216
  tabId: this.tabId,
27216
27217
  ts: p.ts,
27217
- span: p.span
27218
+ span: p.span,
27218
27219
  };
27219
27220
  });
27220
27221
  await this.db.appendSpans(records);
@@ -27263,7 +27264,7 @@ class CrashBufferService {
27263
27264
  const [rrweb, spans, attrs] = await Promise.all([
27264
27265
  this._safe(() => this.db.getRrwebEventsWindow(this.tabId, rrwebFromTs, toTs), []),
27265
27266
  this._safe(() => this.db.getOtelSpansWindow(this.tabId, fromTs, toTs), []),
27266
- this._safe(() => this.db.getAttrs(this.tabId), null)
27267
+ this._safe(() => this.db.getAttrs(this.tabId), null),
27267
27268
  ]);
27268
27269
  const rrwebSorted = rrweb
27269
27270
  .sort((a, b) => a.ts - b.ts)
@@ -27284,12 +27285,12 @@ class CrashBufferService {
27284
27285
  ? {
27285
27286
  sessionAttributes: attrs.sessionAttributes,
27286
27287
  resourceAttributes: attrs.resourceAttributes,
27287
- userAttributes: attrs.userAttributes
27288
+ userAttributes: attrs.userAttributes,
27288
27289
  }
27289
27290
  : null,
27290
27291
  windowMs: this.windowMs,
27291
27292
  fromTs: replayStartTs,
27292
- toTs
27293
+ toTs,
27293
27294
  };
27294
27295
  }
27295
27296
  async clear() {
@@ -27443,7 +27444,7 @@ class IndexedDBService {
27443
27444
  const db = await this.dbPromise;
27444
27445
  const payload = {
27445
27446
  ...attrs,
27446
- updatedAt: (_a = attrs.updatedAt) !== null && _a !== void 0 ? _a : Date.now()
27447
+ updatedAt: (_a = attrs.updatedAt) !== null && _a !== void 0 ? _a : Date.now(),
27447
27448
  };
27448
27449
  return new Promise((resolve, reject) => {
27449
27450
  const tx = db.transaction(attrsStore, 'readwrite');
@@ -27686,7 +27687,7 @@ class IndexedDBService {
27686
27687
  const r = attr.delete(tabId);
27687
27688
  r.onsuccess = () => res();
27688
27689
  r.onerror = () => rej(r.error);
27689
- })
27690
+ }),
27690
27691
  ])
27691
27692
  .then(() => {
27692
27693
  // noop
@@ -31040,13 +31041,13 @@ var SessionRecorderIdGenerator = /** @class */ (function () {
31040
31041
  this.generateShortId = (0,_sdk__WEBPACK_IMPORTED_MODULE_1__.getIdGenerator)(8);
31041
31042
  this.sessionShortId = '';
31042
31043
  this.clientId = '';
31043
- this.sessionType = _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL;
31044
+ this.sessionType;
31044
31045
  }
31045
31046
  SessionRecorderIdGenerator.prototype.generateTraceId = function () {
31046
31047
  var traceId = this.generateLongId();
31047
- if (!this.sessionShortId
31048
- && !this.sessionType
31049
- && !this.clientId) {
31048
+ if ((!this.sessionShortId
31049
+ && !this.clientId)
31050
+ || !this.sessionType) {
31050
31051
  return traceId;
31051
31052
  }
31052
31053
  var sessionTypePrefix = _constants_constants_base__WEBPACK_IMPORTED_MODULE_2__.MULTIPLAYER_TRACE_PREFIX_MAP[this.sessionType];
@@ -31058,7 +31059,6 @@ var SessionRecorderIdGenerator = /** @class */ (function () {
31058
31059
  return this.generateShortId();
31059
31060
  };
31060
31061
  SessionRecorderIdGenerator.prototype.setSessionId = function (sessionShortId, sessionType, clientId) {
31061
- if (sessionType === void 0) { sessionType = _type__WEBPACK_IMPORTED_MODULE_0__.SessionType.MANUAL; }
31062
31062
  if (clientId === void 0) { clientId = ''; }
31063
31063
  if (!clientId &&
31064
31064
  [
@@ -31426,7 +31426,7 @@ var SessionRecorderBrowserTraceExporter = /** @class */ (function () {
31426
31426
  window.postMessage({
31427
31427
  action: 'traces',
31428
31428
  type: this.postMessageType,
31429
- payload: spans.map(function (span) { return _this.serializeSpan(span); })
31429
+ payload: spans.map(function (span) { return _this.serializeSpan(span); }),
31430
31430
  }, this.postMessageTargetOrigin);
31431
31431
  resultCallback({ code: 0 });
31432
31432
  }
@@ -31444,7 +31444,7 @@ var SessionRecorderBrowserTraceExporter = /** @class */ (function () {
31444
31444
  headers: __assign(__assign({ 'Content-Type': 'application/json' }, (this.config.apiKey ? { Authorization: this.config.apiKey } : {})), (this.config.headers || {})),
31445
31445
  timeoutMillis: this.config.timeoutMillis,
31446
31446
  keepAlive: this.config.keepAlive,
31447
- concurrencyLimit: this.config.concurrencyLimit
31447
+ concurrencyLimit: this.config.concurrencyLimit,
31448
31448
  });
31449
31449
  };
31450
31450
  SessionRecorderBrowserTraceExporter.prototype.setApiKey = function (apiKey) {