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