@sentry/replay 7.65.0-alpha.0 → 7.66.0-alpha.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/cjs/index.js +179 -159
- package/cjs/index.js.map +1 -1
- package/esm/index.js +179 -159
- package/esm/index.js.map +1 -1
- package/package.json +5 -5
- package/types/replay.d.ts +12 -2
- package/types/replay.d.ts.map +1 -1
- package/types/session/createSession.d.ts +3 -1
- package/types/session/createSession.d.ts.map +1 -1
- package/types/session/loadOrCreateSession.d.ts +11 -0
- package/types/session/loadOrCreateSession.d.ts.map +1 -0
- package/types/session/shouldRefreshSession.d.ts +4 -0
- package/types/session/shouldRefreshSession.d.ts.map +1 -0
- package/types/types/replay.d.ts +0 -5
- package/types/types/replay.d.ts.map +1 -1
- package/types/session/getSession.d.ts +0 -18
- package/types/session/getSession.d.ts.map +0 -1
package/cjs/index.js
CHANGED
|
@@ -5699,41 +5699,6 @@ function deleteSession() {
|
|
|
5699
5699
|
}
|
|
5700
5700
|
}
|
|
5701
5701
|
|
|
5702
|
-
/**
|
|
5703
|
-
* Given an initial timestamp and an expiry duration, checks to see if current
|
|
5704
|
-
* time should be considered as expired.
|
|
5705
|
-
*/
|
|
5706
|
-
function isExpired(
|
|
5707
|
-
initialTime,
|
|
5708
|
-
expiry,
|
|
5709
|
-
targetTime = +new Date(),
|
|
5710
|
-
) {
|
|
5711
|
-
// Always expired if < 0
|
|
5712
|
-
if (initialTime === null || expiry === undefined || expiry < 0) {
|
|
5713
|
-
return true;
|
|
5714
|
-
}
|
|
5715
|
-
|
|
5716
|
-
// Never expires if == 0
|
|
5717
|
-
if (expiry === 0) {
|
|
5718
|
-
return false;
|
|
5719
|
-
}
|
|
5720
|
-
|
|
5721
|
-
return initialTime + expiry <= targetTime;
|
|
5722
|
-
}
|
|
5723
|
-
|
|
5724
|
-
/**
|
|
5725
|
-
* Checks to see if session is expired
|
|
5726
|
-
*/
|
|
5727
|
-
function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
5728
|
-
return (
|
|
5729
|
-
// First, check that maximum session length has not been exceeded
|
|
5730
|
-
isExpired(session.started, timeouts.maxSessionLife, targetTime) ||
|
|
5731
|
-
// check that the idle timeout has not been exceeded (i.e. user has
|
|
5732
|
-
// performed an action within the last `sessionIdleExpire` ms)
|
|
5733
|
-
isExpired(session.lastActivity, timeouts.sessionIdleExpire, targetTime)
|
|
5734
|
-
);
|
|
5735
|
-
}
|
|
5736
|
-
|
|
5737
5702
|
/**
|
|
5738
5703
|
* Given a sample rate, returns true if replay should be sampled.
|
|
5739
5704
|
*
|
|
@@ -5775,7 +5740,7 @@ function makeSession(session) {
|
|
|
5775
5740
|
const lastActivity = session.lastActivity || now;
|
|
5776
5741
|
const segmentId = session.segmentId || 0;
|
|
5777
5742
|
const sampled = session.sampled;
|
|
5778
|
-
const
|
|
5743
|
+
const previousSessionId = session.previousSessionId;
|
|
5779
5744
|
|
|
5780
5745
|
return {
|
|
5781
5746
|
id,
|
|
@@ -5783,7 +5748,7 @@ function makeSession(session) {
|
|
|
5783
5748
|
lastActivity,
|
|
5784
5749
|
segmentId,
|
|
5785
5750
|
sampled,
|
|
5786
|
-
|
|
5751
|
+
previousSessionId,
|
|
5787
5752
|
};
|
|
5788
5753
|
}
|
|
5789
5754
|
|
|
@@ -5799,10 +5764,14 @@ function getSessionSampleType(sessionSampleRate, allowBuffering) {
|
|
|
5799
5764
|
* that all replays will be saved to as attachments. Currently, we only expect
|
|
5800
5765
|
* one of these Sentry events per "replay session".
|
|
5801
5766
|
*/
|
|
5802
|
-
function createSession(
|
|
5767
|
+
function createSession(
|
|
5768
|
+
{ sessionSampleRate, allowBuffering, stickySession = false },
|
|
5769
|
+
{ previousSessionId } = {},
|
|
5770
|
+
) {
|
|
5803
5771
|
const sampled = getSessionSampleType(sessionSampleRate, allowBuffering);
|
|
5804
5772
|
const session = makeSession({
|
|
5805
5773
|
sampled,
|
|
5774
|
+
previousSessionId,
|
|
5806
5775
|
});
|
|
5807
5776
|
|
|
5808
5777
|
if (stickySession) {
|
|
@@ -5839,49 +5808,83 @@ function fetchSession(traceInternals) {
|
|
|
5839
5808
|
}
|
|
5840
5809
|
|
|
5841
5810
|
/**
|
|
5842
|
-
*
|
|
5811
|
+
* Given an initial timestamp and an expiry duration, checks to see if current
|
|
5812
|
+
* time should be considered as expired.
|
|
5843
5813
|
*/
|
|
5844
|
-
function
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
// If session exists and is passed, use it instead of always hitting session storage
|
|
5853
|
-
const session = currentSession || (stickySession && fetchSession(traceInternals));
|
|
5854
|
-
|
|
5855
|
-
if (session) {
|
|
5856
|
-
// If there is a session, check if it is valid (e.g. "last activity" time
|
|
5857
|
-
// should be within the "session idle time", and "session started" time is
|
|
5858
|
-
// within "max session time").
|
|
5859
|
-
const isExpired = isSessionExpired(session, timeouts);
|
|
5860
|
-
|
|
5861
|
-
if (!isExpired || (allowBuffering && session.shouldRefresh)) {
|
|
5862
|
-
return { type: 'saved', session };
|
|
5863
|
-
} else if (!session.shouldRefresh) {
|
|
5864
|
-
// This is the case if we have an error session that is completed
|
|
5865
|
-
// (=triggered an error). Session will continue as session-based replay,
|
|
5866
|
-
// and when this session is expired, it will not be renewed until user
|
|
5867
|
-
// reloads.
|
|
5868
|
-
const discardedSession = makeSession({ sampled: false });
|
|
5869
|
-
logInfoNextTick('[Replay] Session should not be refreshed', traceInternals);
|
|
5870
|
-
return { type: 'new', session: discardedSession };
|
|
5871
|
-
} else {
|
|
5872
|
-
logInfoNextTick('[Replay] Session has expired', traceInternals);
|
|
5873
|
-
}
|
|
5874
|
-
// Otherwise continue to create a new session
|
|
5814
|
+
function isExpired(
|
|
5815
|
+
initialTime,
|
|
5816
|
+
expiry,
|
|
5817
|
+
targetTime = +new Date(),
|
|
5818
|
+
) {
|
|
5819
|
+
// Always expired if < 0
|
|
5820
|
+
if (initialTime === null || expiry === undefined || expiry < 0) {
|
|
5821
|
+
return true;
|
|
5875
5822
|
}
|
|
5876
5823
|
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5824
|
+
// Never expires if == 0
|
|
5825
|
+
if (expiry === 0) {
|
|
5826
|
+
return false;
|
|
5827
|
+
}
|
|
5828
|
+
|
|
5829
|
+
return initialTime + expiry <= targetTime;
|
|
5830
|
+
}
|
|
5831
|
+
|
|
5832
|
+
/**
|
|
5833
|
+
* Checks to see if session is expired
|
|
5834
|
+
*/
|
|
5835
|
+
function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
5836
|
+
return (
|
|
5837
|
+
// First, check that maximum session length has not been exceeded
|
|
5838
|
+
isExpired(session.started, timeouts.maxSessionLife, targetTime) ||
|
|
5839
|
+
// check that the idle timeout has not been exceeded (i.e. user has
|
|
5840
|
+
// performed an action within the last `sessionIdleExpire` ms)
|
|
5841
|
+
isExpired(session.lastActivity, timeouts.sessionIdleExpire, targetTime)
|
|
5842
|
+
);
|
|
5843
|
+
}
|
|
5844
|
+
|
|
5845
|
+
/** If the session should be refreshed or not. */
|
|
5846
|
+
function shouldRefreshSession(session, timeouts) {
|
|
5847
|
+
// If not expired, all good, just keep the session
|
|
5848
|
+
if (!isSessionExpired(session, timeouts)) {
|
|
5849
|
+
return false;
|
|
5850
|
+
}
|
|
5851
|
+
|
|
5852
|
+
// If we are buffering & haven't ever flushed yet, always continue
|
|
5853
|
+
if (session.sampled === 'buffer' && session.segmentId === 0) {
|
|
5854
|
+
return false;
|
|
5855
|
+
}
|
|
5856
|
+
|
|
5857
|
+
return true;
|
|
5858
|
+
}
|
|
5859
|
+
|
|
5860
|
+
/**
|
|
5861
|
+
* Get or create a session, when initializing the replay.
|
|
5862
|
+
* Returns a session that may be unsampled.
|
|
5863
|
+
*/
|
|
5864
|
+
function loadOrCreateSession(
|
|
5865
|
+
{
|
|
5866
|
+
timeouts,
|
|
5867
|
+
traceInternals,
|
|
5868
|
+
previousSessionId,
|
|
5869
|
+
}
|
|
5870
|
+
|
|
5871
|
+
,
|
|
5872
|
+
sessionOptions,
|
|
5873
|
+
) {
|
|
5874
|
+
const existingSession = sessionOptions.stickySession && fetchSession(traceInternals);
|
|
5875
|
+
|
|
5876
|
+
// No session exists yet, just create a new one
|
|
5877
|
+
if (!existingSession) {
|
|
5878
|
+
logInfoNextTick('[Replay] Creating new session', traceInternals);
|
|
5879
|
+
return createSession(sessionOptions, { previousSessionId });
|
|
5880
|
+
}
|
|
5881
|
+
|
|
5882
|
+
if (!shouldRefreshSession(existingSession, timeouts)) {
|
|
5883
|
+
return existingSession;
|
|
5884
|
+
}
|
|
5883
5885
|
|
|
5884
|
-
|
|
5886
|
+
logInfoNextTick('[Replay] Session in sessionStorage is expired, creating new one...');
|
|
5887
|
+
return createSession(sessionOptions, { previousSessionId: existingSession.id });
|
|
5885
5888
|
}
|
|
5886
5889
|
|
|
5887
5890
|
function isCustomEvent(event) {
|
|
@@ -8473,7 +8476,7 @@ class ReplayContainer {
|
|
|
8473
8476
|
* Initializes the plugin based on sampling configuration. Should not be
|
|
8474
8477
|
* called outside of constructor.
|
|
8475
8478
|
*/
|
|
8476
|
-
initializeSampling() {
|
|
8479
|
+
initializeSampling(previousSessionId) {
|
|
8477
8480
|
const { errorSampleRate, sessionSampleRate } = this._options;
|
|
8478
8481
|
|
|
8479
8482
|
// If neither sample rate is > 0, then do nothing - user will need to call one of
|
|
@@ -8484,13 +8487,7 @@ class ReplayContainer {
|
|
|
8484
8487
|
|
|
8485
8488
|
// Otherwise if there is _any_ sample rate set, try to load an existing
|
|
8486
8489
|
// session, or create a new one.
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
if (!isSessionSampled) {
|
|
8490
|
-
// This should only occur if `errorSampleRate` is 0 and was unsampled for
|
|
8491
|
-
// session-based replay. In this case there is nothing to do.
|
|
8492
|
-
return;
|
|
8493
|
-
}
|
|
8490
|
+
this._initializeSessionForSampling(previousSessionId);
|
|
8494
8491
|
|
|
8495
8492
|
if (!this.session) {
|
|
8496
8493
|
// This should not happen, something wrong has occurred
|
|
@@ -8498,14 +8495,16 @@ class ReplayContainer {
|
|
|
8498
8495
|
return;
|
|
8499
8496
|
}
|
|
8500
8497
|
|
|
8501
|
-
if (this.session.sampled
|
|
8502
|
-
//
|
|
8503
|
-
//
|
|
8504
|
-
|
|
8505
|
-
// prior SDK version.
|
|
8506
|
-
this.recordingMode = 'buffer';
|
|
8498
|
+
if (this.session.sampled === false) {
|
|
8499
|
+
// This should only occur if `errorSampleRate` is 0 and was unsampled for
|
|
8500
|
+
// session-based replay. In this case there is nothing to do.
|
|
8501
|
+
return;
|
|
8507
8502
|
}
|
|
8508
8503
|
|
|
8504
|
+
// If segmentId > 0, it means we've previously already captured this session
|
|
8505
|
+
// In this case, we still want to continue in `session` recording mode
|
|
8506
|
+
this.recordingMode = this.session.sampled === 'buffer' && this.session.segmentId === 0 ? 'buffer' : 'session';
|
|
8507
|
+
|
|
8509
8508
|
logInfoNextTick(
|
|
8510
8509
|
`[Replay] Starting replay in ${this.recordingMode} mode`,
|
|
8511
8510
|
this._options._experiments.traceInternals,
|
|
@@ -8532,19 +8531,19 @@ class ReplayContainer {
|
|
|
8532
8531
|
|
|
8533
8532
|
logInfoNextTick('[Replay] Starting replay in session mode', this._options._experiments.traceInternals);
|
|
8534
8533
|
|
|
8535
|
-
const
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8534
|
+
const session = loadOrCreateSession(
|
|
8535
|
+
{
|
|
8536
|
+
timeouts: this.timeouts,
|
|
8537
|
+
traceInternals: this._options._experiments.traceInternals,
|
|
8538
|
+
},
|
|
8539
|
+
{
|
|
8540
|
+
stickySession: this._options.stickySession,
|
|
8541
|
+
// This is intentional: create a new session-based replay when calling `start()`
|
|
8542
|
+
sessionSampleRate: 1,
|
|
8543
|
+
allowBuffering: false,
|
|
8544
|
+
},
|
|
8545
|
+
);
|
|
8546
8546
|
|
|
8547
|
-
session.previousSessionId = previousSessionId;
|
|
8548
8547
|
this.session = session;
|
|
8549
8548
|
|
|
8550
8549
|
this._initializeRecording();
|
|
@@ -8561,18 +8560,18 @@ class ReplayContainer {
|
|
|
8561
8560
|
|
|
8562
8561
|
logInfoNextTick('[Replay] Starting replay in buffer mode', this._options._experiments.traceInternals);
|
|
8563
8562
|
|
|
8564
|
-
const
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8563
|
+
const session = loadOrCreateSession(
|
|
8564
|
+
{
|
|
8565
|
+
timeouts: this.timeouts,
|
|
8566
|
+
traceInternals: this._options._experiments.traceInternals,
|
|
8567
|
+
},
|
|
8568
|
+
{
|
|
8569
|
+
stickySession: this._options.stickySession,
|
|
8570
|
+
sessionSampleRate: 0,
|
|
8571
|
+
allowBuffering: true,
|
|
8572
|
+
},
|
|
8573
|
+
);
|
|
8574
8574
|
|
|
8575
|
-
session.previousSessionId = previousSessionId;
|
|
8576
8575
|
this.session = session;
|
|
8577
8576
|
|
|
8578
8577
|
this.recordingMode = 'buffer';
|
|
@@ -8629,15 +8628,18 @@ class ReplayContainer {
|
|
|
8629
8628
|
return;
|
|
8630
8629
|
}
|
|
8631
8630
|
|
|
8631
|
+
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
8632
|
+
// enter into an infinite loop when `stop()` is called while flushing.
|
|
8633
|
+
this._isEnabled = false;
|
|
8634
|
+
|
|
8632
8635
|
try {
|
|
8633
8636
|
logInfo(
|
|
8634
|
-
`[Replay] Stopping Replay${reason ? ` triggered by ${reason}` : ''}
|
|
8637
|
+
`[Replay] Stopping Replay${reason ? ` triggered by ${reason}` : ''} ${new Date().toISOString()} ${
|
|
8638
|
+
this._isEnabled
|
|
8639
|
+
}`,
|
|
8635
8640
|
this._options._experiments.traceInternals,
|
|
8636
8641
|
);
|
|
8637
8642
|
|
|
8638
|
-
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
8639
|
-
// enter into an infinite loop when `stop()` is called while flushing.
|
|
8640
|
-
this._isEnabled = false;
|
|
8641
8643
|
this._removeListeners();
|
|
8642
8644
|
this.stopRecording();
|
|
8643
8645
|
|
|
@@ -8683,7 +8685,7 @@ class ReplayContainer {
|
|
|
8683
8685
|
* new DOM checkout.`
|
|
8684
8686
|
*/
|
|
8685
8687
|
resume() {
|
|
8686
|
-
if (!this._isPaused || !this.
|
|
8688
|
+
if (!this._isPaused || !this._checkSession()) {
|
|
8687
8689
|
return;
|
|
8688
8690
|
}
|
|
8689
8691
|
|
|
@@ -8731,16 +8733,6 @@ class ReplayContainer {
|
|
|
8731
8733
|
|
|
8732
8734
|
// Once this session ends, we do not want to refresh it
|
|
8733
8735
|
if (this.session) {
|
|
8734
|
-
this.session.shouldRefresh = false;
|
|
8735
|
-
|
|
8736
|
-
// It's possible that the session lifespan is > max session lifespan
|
|
8737
|
-
// because we have been buffering beyond max session lifespan (we ignore
|
|
8738
|
-
// expiration given that `shouldRefresh` is true). Since we flip
|
|
8739
|
-
// `shouldRefresh`, the session could be considered expired due to
|
|
8740
|
-
// lifespan, which is not what we want. Update session start date to be
|
|
8741
|
-
// the current timestamp, so that session is not considered to be
|
|
8742
|
-
// expired. This means that max replay duration can be MAX_SESSION_LIFE +
|
|
8743
|
-
// (length of buffer), which we are ok with.
|
|
8744
8736
|
this._updateUserActivity(activityTime);
|
|
8745
8737
|
this._updateSessionActivity(activityTime);
|
|
8746
8738
|
this._maybeSaveSession();
|
|
@@ -8791,7 +8783,7 @@ class ReplayContainer {
|
|
|
8791
8783
|
if (!this._stopRecording) {
|
|
8792
8784
|
// Create a new session, otherwise when the user action is flushed, it
|
|
8793
8785
|
// will get rejected due to an expired session.
|
|
8794
|
-
if (!this.
|
|
8786
|
+
if (!this._checkSession()) {
|
|
8795
8787
|
return;
|
|
8796
8788
|
}
|
|
8797
8789
|
|
|
@@ -8890,7 +8882,7 @@ class ReplayContainer {
|
|
|
8890
8882
|
|
|
8891
8883
|
// --- There is recent user activity --- //
|
|
8892
8884
|
// This will create a new session if expired, based on expiry length
|
|
8893
|
-
if (!this.
|
|
8885
|
+
if (!this._checkSession()) {
|
|
8894
8886
|
return;
|
|
8895
8887
|
}
|
|
8896
8888
|
|
|
@@ -8992,6 +8984,7 @@ class ReplayContainer {
|
|
|
8992
8984
|
|
|
8993
8985
|
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
8994
8986
|
this._isEnabled = true;
|
|
8987
|
+
this._isPaused = false;
|
|
8995
8988
|
|
|
8996
8989
|
this.startRecording();
|
|
8997
8990
|
}
|
|
@@ -9007,39 +9000,62 @@ class ReplayContainer {
|
|
|
9007
9000
|
|
|
9008
9001
|
/**
|
|
9009
9002
|
* Loads (or refreshes) the current session.
|
|
9010
|
-
* Returns false if session is not recorded.
|
|
9011
9003
|
*/
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9004
|
+
_initializeSessionForSampling(previousSessionId) {
|
|
9005
|
+
// Whenever there is _any_ error sample rate, we always allow buffering
|
|
9006
|
+
// Because we decide on sampling when an error occurs, we need to buffer at all times if sampling for errors
|
|
9007
|
+
const allowBuffering = this._options.errorSampleRate > 0;
|
|
9008
|
+
|
|
9009
|
+
const session = loadOrCreateSession(
|
|
9010
|
+
{
|
|
9011
|
+
timeouts: this.timeouts,
|
|
9012
|
+
traceInternals: this._options._experiments.traceInternals,
|
|
9013
|
+
previousSessionId,
|
|
9014
|
+
},
|
|
9015
|
+
{
|
|
9016
|
+
stickySession: this._options.stickySession,
|
|
9017
|
+
sessionSampleRate: this._options.sessionSampleRate,
|
|
9018
|
+
allowBuffering,
|
|
9019
|
+
},
|
|
9020
|
+
);
|
|
9021
9021
|
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
if (type === 'new') {
|
|
9025
|
-
this.setInitialState();
|
|
9026
|
-
}
|
|
9022
|
+
this.session = session;
|
|
9023
|
+
}
|
|
9027
9024
|
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9025
|
+
/**
|
|
9026
|
+
* Checks and potentially refreshes the current session.
|
|
9027
|
+
* Returns false if session is not recorded.
|
|
9028
|
+
*/
|
|
9029
|
+
_checkSession() {
|
|
9030
|
+
// If there is no session yet, we do not want to refresh anything
|
|
9031
|
+
// This should generally not happen, but to be safe....
|
|
9032
|
+
if (!this.session) {
|
|
9033
|
+
return false;
|
|
9031
9034
|
}
|
|
9032
9035
|
|
|
9033
|
-
|
|
9036
|
+
const currentSession = this.session;
|
|
9034
9037
|
|
|
9035
|
-
if (
|
|
9036
|
-
void this.
|
|
9038
|
+
if (shouldRefreshSession(currentSession, this.timeouts)) {
|
|
9039
|
+
void this._refreshSession(currentSession);
|
|
9037
9040
|
return false;
|
|
9038
9041
|
}
|
|
9039
9042
|
|
|
9040
9043
|
return true;
|
|
9041
9044
|
}
|
|
9042
9045
|
|
|
9046
|
+
/**
|
|
9047
|
+
* Refresh a session with a new one.
|
|
9048
|
+
* This stops the current session (without forcing a flush, as that would never work since we are expired),
|
|
9049
|
+
* and then does a new sampling based on the refreshed session.
|
|
9050
|
+
*/
|
|
9051
|
+
async _refreshSession(session) {
|
|
9052
|
+
if (!this._isEnabled) {
|
|
9053
|
+
return;
|
|
9054
|
+
}
|
|
9055
|
+
await this.stop({ reason: 'refresh session' });
|
|
9056
|
+
this.initializeSampling(session.id);
|
|
9057
|
+
}
|
|
9058
|
+
|
|
9043
9059
|
/**
|
|
9044
9060
|
* Adds listeners to record events for the replay
|
|
9045
9061
|
*/
|
|
@@ -9296,7 +9312,9 @@ class ReplayContainer {
|
|
|
9296
9312
|
* Should never be called directly, only by `flush`
|
|
9297
9313
|
*/
|
|
9298
9314
|
async _runFlush() {
|
|
9299
|
-
|
|
9315
|
+
const replayId = this.getSessionId();
|
|
9316
|
+
|
|
9317
|
+
if (!this.session || !this.eventBuffer || !replayId) {
|
|
9300
9318
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.error('[Replay] No session or eventBuffer found to flush.');
|
|
9301
9319
|
return;
|
|
9302
9320
|
}
|
|
@@ -9316,13 +9334,15 @@ class ReplayContainer {
|
|
|
9316
9334
|
return;
|
|
9317
9335
|
}
|
|
9318
9336
|
|
|
9337
|
+
// if this changed in the meanwhile, e.g. because the session was refreshed or similar, we abort here
|
|
9338
|
+
if (replayId !== this.getSessionId()) {
|
|
9339
|
+
return;
|
|
9340
|
+
}
|
|
9341
|
+
|
|
9319
9342
|
try {
|
|
9320
9343
|
// This uses the data from the eventBuffer, so we need to call this before `finish()
|
|
9321
9344
|
this._updateInitialTimestampFromEventBuffer();
|
|
9322
9345
|
|
|
9323
|
-
// Note this empties the event buffer regardless of outcome of sending replay
|
|
9324
|
-
const recordingData = await this.eventBuffer.finish();
|
|
9325
|
-
|
|
9326
9346
|
const timestamp = Date.now();
|
|
9327
9347
|
|
|
9328
9348
|
// Check total duration again, to avoid sending outdated stuff
|
|
@@ -9332,14 +9352,14 @@ class ReplayContainer {
|
|
|
9332
9352
|
throw new Error('Session is too long, not sending replay');
|
|
9333
9353
|
}
|
|
9334
9354
|
|
|
9335
|
-
// NOTE: Copy values from instance members, as it's possible they could
|
|
9336
|
-
// change before the flush finishes.
|
|
9337
|
-
const replayId = this.session.id;
|
|
9338
9355
|
const eventContext = this._popEventContext();
|
|
9339
9356
|
// Always increment segmentId regardless of outcome of sending replay
|
|
9340
9357
|
const segmentId = this.session.segmentId++;
|
|
9341
9358
|
this._maybeSaveSession();
|
|
9342
9359
|
|
|
9360
|
+
// Note this empties the event buffer regardless of outcome of sending replay
|
|
9361
|
+
const recordingData = await this.eventBuffer.finish();
|
|
9362
|
+
|
|
9343
9363
|
await sendReplay({
|
|
9344
9364
|
replayId,
|
|
9345
9365
|
recordingData,
|