@multiplayer-app/session-recorder-browser 1.2.25 → 1.2.27

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/index.js CHANGED
@@ -24284,7 +24284,7 @@ const DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE = 100000;
24284
24284
  const SESSION_RESPONSE = 'multiplayer-debug-session-response';
24285
24285
  const CONTINUOUS_DEBUGGING_TIMEOUT = 60000; // 1 minutes
24286
24286
  const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30; // TODO: move to shared config otel core
24287
- const PACKAGE_VERSION_EXPORT = "1.2.25" || 0;
24287
+ const PACKAGE_VERSION_EXPORT = "1.2.27" || 0;
24288
24288
  // Regex patterns for OpenTelemetry ignore URLs
24289
24289
  const OTEL_IGNORE_URLS = [
24290
24290
  // Traces endpoint
@@ -25130,6 +25130,9 @@ const getExporterEndpoint = (exporterEndpoint) => {
25130
25130
  /* harmony import */ var _opentelemetry_instrumentation__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @opentelemetry/instrumentation */ "../../node_modules/@opentelemetry/instrumentation/build/esm/autoLoader.js");
25131
25131
  /* harmony import */ var _opentelemetry_auto_instrumentations_web__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @opentelemetry/auto-instrumentations-web */ "../../node_modules/@opentelemetry/auto-instrumentations-web/build/esm/index.js");
25132
25132
  /* harmony import */ var _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @multiplayer-app/session-recorder-common */ "../session-recorder-common/dist/esm/index-browser.js");
25133
+ /* harmony import */ var _opentelemetry_api__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @opentelemetry/api */ "../../node_modules/@opentelemetry/api/build/esm/trace-api.js");
25134
+ /* harmony import */ var _opentelemetry_api__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @opentelemetry/api */ "../../node_modules/@opentelemetry/api/build/esm/context-api.js");
25135
+ /* harmony import */ var _opentelemetry_api__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @opentelemetry/api */ "../../node_modules/@opentelemetry/api/build/esm/trace/status.js");
25133
25136
  /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config */ "./src/config/index.ts");
25134
25137
  /* harmony import */ var _helpers__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./helpers */ "./src/otel/helpers.ts");
25135
25138
 
@@ -25142,10 +25145,13 @@ const getExporterEndpoint = (exporterEndpoint) => {
25142
25145
 
25143
25146
 
25144
25147
 
25148
+
25149
+
25145
25150
  class TracerBrowserSDK {
25146
25151
  constructor() {
25147
25152
  this.allowedElements = new Set(['A', 'BUTTON']);
25148
25153
  this.sessionId = '';
25154
+ this.globalErrorListenersRegistered = false;
25149
25155
  }
25150
25156
  setSessionId(sessionId, sessionType = _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionType.PLAIN) {
25151
25157
  this.sessionId = sessionId;
@@ -25284,6 +25290,7 @@ class TracerBrowserSDK {
25284
25290
  }),
25285
25291
  ],
25286
25292
  });
25293
+ this._registerGlobalErrorListeners();
25287
25294
  }
25288
25295
  start(sessionId, sessionType) {
25289
25296
  if (!this.tracerProvider) {
@@ -25303,6 +25310,46 @@ class TracerBrowserSDK {
25303
25310
  }
25304
25311
  this.exporter.setApiKey(apiKey);
25305
25312
  }
25313
+ /**
25314
+ * Capture an exception as an error span/event.
25315
+ * If there is an active span, the exception will be recorded on it.
25316
+ * Otherwise, a short-lived span will be created to hold the exception event.
25317
+ */
25318
+ captureException(error, errorInfo) {
25319
+ if (!error)
25320
+ return;
25321
+ // Prefer attaching to the active span to keep correlation intact
25322
+ try {
25323
+ const activeSpan = _opentelemetry_api__WEBPACK_IMPORTED_MODULE_10__.trace.getSpan(_opentelemetry_api__WEBPACK_IMPORTED_MODULE_11__.context.active());
25324
+ if (activeSpan) {
25325
+ // Standard OTEL exception event + span status
25326
+ _multiplayer_app_session_recorder_common__WEBPACK_IMPORTED_MODULE_1__.SessionRecorderSdk.captureException(error);
25327
+ activeSpan.addEvent('exception', {
25328
+ 'exception.type': error.name || 'Error',
25329
+ 'exception.message': error.message,
25330
+ 'exception.stacktrace': error.stack || '',
25331
+ ...(errorInfo || {}),
25332
+ });
25333
+ return;
25334
+ }
25335
+ }
25336
+ catch (_ignored) { }
25337
+ // Fallback: create a short-lived span to hold the exception details
25338
+ try {
25339
+ const tracer = _opentelemetry_api__WEBPACK_IMPORTED_MODULE_10__.trace.getTracer('exception');
25340
+ const span = tracer.startSpan(error.name || 'Error');
25341
+ span.recordException(error);
25342
+ span.setStatus({ code: _opentelemetry_api__WEBPACK_IMPORTED_MODULE_12__.SpanStatusCode.ERROR, message: error.message });
25343
+ span.addEvent('exception', {
25344
+ 'exception.type': error.name || 'Error',
25345
+ 'exception.message': error.message,
25346
+ 'exception.stacktrace': error.stack || '',
25347
+ ...(errorInfo || {}),
25348
+ });
25349
+ span.end();
25350
+ }
25351
+ catch (_ignored) { }
25352
+ }
25306
25353
  _getSpanSessionIdProcessor() {
25307
25354
  return {
25308
25355
  forceFlush: () => Promise.resolve(),
@@ -25316,6 +25363,28 @@ class TracerBrowserSDK {
25316
25363
  },
25317
25364
  };
25318
25365
  }
25366
+ _registerGlobalErrorListeners() {
25367
+ if (this.globalErrorListenersRegistered)
25368
+ return;
25369
+ if (typeof window === 'undefined')
25370
+ return;
25371
+ const errorHandler = (event) => {
25372
+ const err = (event === null || event === void 0 ? void 0 : event.error) instanceof Error
25373
+ ? event.error
25374
+ : new Error((event === null || event === void 0 ? void 0 : event.message) || 'Script error');
25375
+ this.captureException(err);
25376
+ };
25377
+ const rejectionHandler = (event) => {
25378
+ const reason = (event && 'reason' in event) ? event.reason : undefined;
25379
+ const err = reason instanceof Error
25380
+ ? reason
25381
+ : new Error(typeof reason === 'string' ? reason : 'Unhandled promise rejection');
25382
+ this.captureException(err);
25383
+ };
25384
+ window.addEventListener('error', errorHandler);
25385
+ window.addEventListener('unhandledrejection', rejectionHandler);
25386
+ this.globalErrorListenersRegistered = true;
25387
+ }
25319
25388
  }
25320
25389
 
25321
25390
 
@@ -26506,6 +26575,19 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26506
26575
  set recordingButtonClickHandler(handler) {
26507
26576
  this._sessionWidget.buttonClickExternalHandler = handler;
26508
26577
  }
26578
+ /**
26579
+ * Capture an exception manually and send it as an error trace.
26580
+ */
26581
+ captureException(error, errorInfo) {
26582
+ try {
26583
+ const normalizedError = this._normalizeError(error);
26584
+ const normalizedErrorInfo = this._normalizeErrorInfo(errorInfo);
26585
+ this._tracer.captureException(normalizedError, normalizedErrorInfo);
26586
+ }
26587
+ catch (e) {
26588
+ this.error = (e === null || e === void 0 ? void 0 : e.message) || 'Failed to capture exception';
26589
+ }
26590
+ }
26509
26591
  /**
26510
26592
  * @description Check if session should be started/stopped automatically
26511
26593
  * @param {ISession} [sessionPayload]
@@ -26753,6 +26835,28 @@ class SessionRecorder extends lib0_observable__WEBPACK_IMPORTED_MODULE_14__.Obse
26753
26835
  break;
26754
26836
  }
26755
26837
  }
26838
+ _normalizeError(error) {
26839
+ if (error instanceof Error)
26840
+ return error;
26841
+ if (typeof error === 'string')
26842
+ return new Error(error);
26843
+ try {
26844
+ return new Error(JSON.stringify(error));
26845
+ }
26846
+ catch (_e) {
26847
+ return new Error(String(error));
26848
+ }
26849
+ }
26850
+ _normalizeErrorInfo(errorInfo) {
26851
+ if (!errorInfo)
26852
+ return {};
26853
+ try {
26854
+ return JSON.parse(JSON.stringify(errorInfo));
26855
+ }
26856
+ catch (_e) {
26857
+ return { errorInfo: String(errorInfo) };
26858
+ }
26859
+ }
26756
26860
  }
26757
26861
 
26758
26862