@sentry/replay 7.88.0 → 7.90.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/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getCurrentHub, getClient, isSentryRequestUrl, addEventProcessor, prepareEvent, setContext, captureException } from '@sentry/core';
1
+ import { addBreadcrumb, getClient, isSentryRequestUrl, getCurrentScope, addEventProcessor, prepareEvent, setContext, captureException } from '@sentry/core';
2
2
  import { GLOBAL_OBJ, normalize, fill, htmlTreeAsString, browserPerformanceTimeOrigin, logger, uuid4, SENTRY_XHR_DATA_KEY, dropUndefinedKeys, stringMatchesSomePattern, addFetchInstrumentationHandler, addXhrInstrumentationHandler, addClickKeypressInstrumentationHandler, addHistoryInstrumentationHandler, createEnvelope, createEventEnvelopeHeaders, getSdkMetadataForEnvelopeHeader, updateRateLimits, isRateLimited, consoleSandbox, isBrowser } from '@sentry/utils';
3
3
  import { addPerformanceInstrumentationHandler, addLcpInstrumentationHandler } from '@sentry-internal/tracing';
4
4
 
@@ -52,6 +52,36 @@ const MIN_REPLAY_DURATION_LIMIT = 15000;
52
52
  /** The max. length of a replay. */
53
53
  const MAX_REPLAY_DURATION = 3600000; // 60 minutes in ms;
54
54
 
55
+ const CANVAS_QUALITY = {
56
+ low: {
57
+ sampling: {
58
+ canvas: 1,
59
+ },
60
+ dataURLOptions: {
61
+ type: 'image/webp',
62
+ quality: 0.25,
63
+ },
64
+ },
65
+ medium: {
66
+ sampling: {
67
+ canvas: 2,
68
+ },
69
+ dataURLOptions: {
70
+ type: 'image/webp',
71
+ quality: 0.4,
72
+ },
73
+ },
74
+ high: {
75
+ sampling: {
76
+ canvas: 4,
77
+ },
78
+ dataURLOptions: {
79
+ type: 'image/webp',
80
+ quality: 0.5,
81
+ },
82
+ },
83
+ };
84
+
55
85
  var NodeType$1;
56
86
  (function (NodeType) {
57
87
  NodeType[NodeType["Document"] = 0] = "Document";
@@ -3914,7 +3944,9 @@ function addBreadcrumbEvent(replay, breadcrumb) {
3914
3944
  }
3915
3945
 
3916
3946
  replay.addUpdate(() => {
3917
- void replay.throttledAddEvent({
3947
+ // This should never reject
3948
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
3949
+ replay.throttledAddEvent({
3918
3950
  type: EventType.Custom,
3919
3951
  // TODO: We were converting from ms to seconds for breadcrumbs, spans,
3920
3952
  // but maybe we should just keep them as milliseconds
@@ -4737,7 +4769,7 @@ function logInfo(message, shouldAddBreadcrumb) {
4737
4769
  logger.info(message);
4738
4770
 
4739
4771
  if (shouldAddBreadcrumb) {
4740
- addBreadcrumb(message);
4772
+ addLogBreadcrumb(message);
4741
4773
  }
4742
4774
  }
4743
4775
 
@@ -4756,14 +4788,13 @@ function logInfoNextTick(message, shouldAddBreadcrumb) {
4756
4788
  // Wait a tick here to avoid race conditions for some initial logs
4757
4789
  // which may be added before replay is initialized
4758
4790
  setTimeout(() => {
4759
- addBreadcrumb(message);
4791
+ addLogBreadcrumb(message);
4760
4792
  }, 0);
4761
4793
  }
4762
4794
  }
4763
4795
 
4764
- function addBreadcrumb(message) {
4765
- const hub = getCurrentHub();
4766
- hub.addBreadcrumb(
4796
+ function addLogBreadcrumb(message) {
4797
+ addBreadcrumb(
4767
4798
  {
4768
4799
  category: 'console',
4769
4800
  data: {
@@ -5029,7 +5060,9 @@ class EventBufferCompressionWorker {
5029
5060
  this.hasCheckout = false;
5030
5061
 
5031
5062
  // We do not wait on this, as we assume the order of messages is consistent for the worker
5032
- void this._worker.postMessage('clear');
5063
+ this._worker.postMessage('clear').then(null, e => {
5064
+ DEBUG_BUILD && logger.warn('[Replay] Sending "clear" message to worker failed', e);
5065
+ });
5033
5066
  }
5034
5067
 
5035
5068
  /** @inheritdoc */
@@ -5465,7 +5498,9 @@ function addEventSync(replay, event, isCheckout) {
5465
5498
  return false;
5466
5499
  }
5467
5500
 
5468
- void _addEvent(replay, event, isCheckout);
5501
+ // This should never reject
5502
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
5503
+ _addEvent(replay, event, isCheckout);
5469
5504
 
5470
5505
  return true;
5471
5506
  }
@@ -5662,7 +5697,9 @@ function handleErrorEvent(replay, event) {
5662
5697
 
5663
5698
  setTimeout(() => {
5664
5699
  // Capture current event buffer as new replay
5665
- void replay.sendBufferedReplayOrFlush();
5700
+ // This should never reject
5701
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
5702
+ replay.sendBufferedReplayOrFlush();
5666
5703
  });
5667
5704
  }
5668
5705
 
@@ -5706,8 +5743,9 @@ function handleHydrationError(replay, event) {
5706
5743
  // Example https://reactjs.org/docs/error-decoder.html?invariant=423
5707
5744
  exceptionValue.match(/reactjs\.org\/docs\/error-decoder\.html\?invariant=(418|419|422|423|425)/) ||
5708
5745
  // Development builds of react-dom
5709
- // Example Text: content did not match. Server: "A" Client: "B"
5710
- exceptionValue.match(/(hydration|content does not match|did not match)/i)
5746
+ // Error 1: Hydration failed because the initial UI does not match what was rendered on the server.
5747
+ // Error 2: Text content does not match server-rendered HTML. Warning: Text content did not match.
5748
+ exceptionValue.match(/(does not match server-rendered HTML|Hydration failed because)/i)
5711
5749
  ) {
5712
5750
  const breadcrumb = createBreadcrumb({
5713
5751
  category: 'replay.hydrate-error',
@@ -5744,7 +5782,9 @@ function addFeedbackBreadcrumb(replay, event) {
5744
5782
  return true;
5745
5783
  }
5746
5784
 
5747
- void replay.throttledAddEvent({
5785
+ // This should never reject
5786
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
5787
+ replay.throttledAddEvent({
5748
5788
  type: EventType.Custom,
5749
5789
  timestamp: event.timestamp * 1000,
5750
5790
  data: {
@@ -5822,7 +5862,9 @@ function handleGlobalEventListener(
5822
5862
  }
5823
5863
 
5824
5864
  if (isFeedbackEvent(event)) {
5825
- void replay.flush();
5865
+ // This should never reject
5866
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
5867
+ replay.flush();
5826
5868
  event.contexts.feedback.replay_id = replay.getSessionId();
5827
5869
  // Add a replay breadcrumb for this piece of feedback
5828
5870
  addFeedbackBreadcrumb(replay, event);
@@ -5943,7 +5985,7 @@ function shouldFilterRequest(replay, url) {
5943
5985
  return false;
5944
5986
  }
5945
5987
 
5946
- return isSentryRequestUrl(url, getCurrentHub());
5988
+ return isSentryRequestUrl(url, getClient());
5947
5989
  }
5948
5990
 
5949
5991
  /** Add a performance entry breadcrumb */
@@ -6876,7 +6918,9 @@ function beforeAddNetworkBreadcrumb(
6876
6918
  // So any async mutations to it will not be reflected in the final breadcrumb
6877
6919
  enrichXhrBreadcrumb(breadcrumb, hint, options);
6878
6920
 
6879
- void captureXhrBreadcrumbToReplay(breadcrumb, hint, options);
6921
+ // This call should not reject
6922
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
6923
+ captureXhrBreadcrumbToReplay(breadcrumb, hint, options);
6880
6924
  }
6881
6925
 
6882
6926
  if (_isFetchBreadcrumb(breadcrumb) && _isFetchHint(hint)) {
@@ -6885,7 +6929,9 @@ function beforeAddNetworkBreadcrumb(
6885
6929
  // So any async mutations to it will not be reflected in the final breadcrumb
6886
6930
  enrichFetchBreadcrumb(breadcrumb, hint, options);
6887
6931
 
6888
- void captureFetchBreadcrumbToReplay(breadcrumb, hint, options);
6932
+ // This call should not reject
6933
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
6934
+ captureFetchBreadcrumbToReplay(breadcrumb, hint, options);
6889
6935
  }
6890
6936
  } catch (e) {
6891
6937
  DEBUG_BUILD && logger.warn('Error when enriching network breadcrumb');
@@ -7021,7 +7067,7 @@ function normalizeConsoleBreadcrumb(
7021
7067
  */
7022
7068
  function addGlobalListeners(replay) {
7023
7069
  // Listeners from core SDK //
7024
- const scope = getCurrentHub().getScope();
7070
+ const scope = getCurrentScope();
7025
7071
  const client = getClient();
7026
7072
 
7027
7073
  scope.addScopeListener(handleScopeListener(replay));
@@ -7068,7 +7114,9 @@ function addGlobalListeners(replay) {
7068
7114
  client.on('beforeSendFeedback', (feedbackEvent, options) => {
7069
7115
  const replayId = replay.getSessionId();
7070
7116
  if (options && options.includeReplay && replay.isEnabled() && replayId) {
7071
- void replay.flush();
7117
+ // This should never reject
7118
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
7119
+ replay.flush();
7072
7120
  if (feedbackEvent.contexts && feedbackEvent.contexts.feedback) {
7073
7121
  feedbackEvent.contexts.feedback.replay_id = replayId;
7074
7122
  }
@@ -7274,6 +7322,9 @@ function getHandleRecordingEmit(replay) {
7274
7322
  // a previous session ID. In this case, we want to buffer events
7275
7323
  // for a set amount of time before flushing. This can help avoid
7276
7324
  // capturing replays of users that immediately close the window.
7325
+
7326
+ // This should never reject
7327
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
7277
7328
  void replay.flush();
7278
7329
  }
7279
7330
 
@@ -7454,9 +7505,8 @@ async function sendReplayRequest({
7454
7505
 
7455
7506
  const { urls, errorIds, traceIds, initialTimestamp } = eventContext;
7456
7507
 
7457
- const hub = getCurrentHub();
7458
- const client = hub.getClient();
7459
- const scope = hub.getScope();
7508
+ const client = getClient();
7509
+ const scope = getCurrentScope();
7460
7510
  const transport = client && client.getTransport();
7461
7511
  const dsn = client && client.getDsn();
7462
7512
 
@@ -7957,12 +8007,12 @@ class ReplayContainer {
7957
8007
  ...(this.recordingMode === 'buffer' && { checkoutEveryNms: BUFFER_CHECKOUT_TIME }),
7958
8008
  emit: getHandleRecordingEmit(this),
7959
8009
  onMutation: this._onMutationHandler,
7960
- ...(canvas && {
7961
- recordCanvas: true,
7962
- sampling: { canvas: canvas.fps || 4 },
7963
- dataURLOptions: { quality: canvas.quality || 0.6 },
7964
- getCanvasManager: canvas.manager,
7965
- }),
8010
+ ...(canvas &&
8011
+ canvas.manager && {
8012
+ recordCanvas: true,
8013
+ getCanvasManager: canvas.manager,
8014
+ ...(CANVAS_QUALITY[canvas.quality || 'medium'] || CANVAS_QUALITY.medium),
8015
+ }),
7966
8016
  });
7967
8017
  } catch (err) {
7968
8018
  this._handleException(err);
@@ -8315,7 +8365,7 @@ class ReplayContainer {
8315
8365
  * This is only available if performance is enabled, and if an instrumented router is used.
8316
8366
  */
8317
8367
  getCurrentRoute() {
8318
- const lastTransaction = this.lastTransaction || getCurrentHub().getScope().getTransaction();
8368
+ const lastTransaction = this.lastTransaction || getCurrentScope().getTransaction();
8319
8369
  if (!lastTransaction || !['route', 'custom'].includes(lastTransaction.metadata.source)) {
8320
8370
  return undefined;
8321
8371
  }
@@ -8402,7 +8452,9 @@ class ReplayContainer {
8402
8452
  maxReplayDuration: this._options.maxReplayDuration,
8403
8453
  })
8404
8454
  ) {
8405
- void this._refreshSession(currentSession);
8455
+ // This should never reject
8456
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8457
+ this._refreshSession(currentSession);
8406
8458
  return false;
8407
8459
  }
8408
8460
 
@@ -8541,6 +8593,8 @@ class ReplayContainer {
8541
8593
  // Send replay when the page/tab becomes hidden. There is no reason to send
8542
8594
  // replay if it becomes visible, since no actions we care about were done
8543
8595
  // while it was hidden
8596
+ // This should never reject
8597
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8544
8598
  void this.conditionalFlush();
8545
8599
  }
8546
8600
 
@@ -8589,7 +8643,9 @@ class ReplayContainer {
8589
8643
  */
8590
8644
  _createCustomBreadcrumb(breadcrumb) {
8591
8645
  this.addUpdate(() => {
8592
- void this.throttledAddEvent({
8646
+ // This should never reject
8647
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8648
+ this.throttledAddEvent({
8593
8649
  type: EventType.Custom,
8594
8650
  timestamp: breadcrumb.timestamp || 0,
8595
8651
  data: {
@@ -8730,7 +8786,9 @@ class ReplayContainer {
8730
8786
  // This means we retried 3 times and all of them failed,
8731
8787
  // or we ran into a problem we don't want to retry, like rate limiting.
8732
8788
  // In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
8733
- void this.stop({ reason: 'sendReplay' });
8789
+ // This should never reject
8790
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8791
+ this.stop({ reason: 'sendReplay' });
8734
8792
 
8735
8793
  const client = getClient();
8736
8794
 
@@ -8849,7 +8907,9 @@ class ReplayContainer {
8849
8907
 
8850
8908
  // Stop replay if over the mutation limit
8851
8909
  if (overMutationLimit) {
8852
- void this.stop({ reason: 'mutationLimit', forceFlush: this.recordingMode === 'session' });
8910
+ // This should never reject
8911
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8912
+ this.stop({ reason: 'mutationLimit', forceFlush: this.recordingMode === 'session' });
8853
8913
  return false;
8854
8914
  }
8855
8915