@@ -18,7 +18,8 @@ import { handleKeyboardEvent } from './coreHandlers/handleKeyboardEvent';
18
18
import { setupPerformanceObserver } from './coreHandlers/performanceObserver' ;
19
19
import { createEventBuffer } from './eventBuffer' ;
20
20
import { clearSession } from './session/clearSession' ;
21
- import { getSession } from './session/getSession' ;
21
+ import { loadOrCreateSession } from './session/loadOrCreateSession' ;
22
+ import { maybeRefreshSession } from './session/maybeRefreshSession' ;
22
23
import { saveSession } from './session/saveSession' ;
23
24
import type {
24
25
AddEventResult ,
@@ -228,28 +229,24 @@ export class ReplayContainer implements ReplayContainerInterface {
228
229
229
230
// Otherwise if there is _any_ sample rate set, try to load an existing
230
231
// session, or create a new one.
231
- const isSessionSampled = this . _loadAndCheckSession ( ) ;
232
-
233
- if ( ! isSessionSampled ) {
234
- // This should only occur if `errorSampleRate` is 0 and was unsampled for
235
- // session-based replay. In this case there is nothing to do.
236
- return ;
237
- }
232
+ this . _initializeSessionForSampling ( ) ;
238
233
239
234
if ( ! this . session ) {
240
235
// This should not happen, something wrong has occurred
241
236
this . _handleException ( new Error ( 'Unable to initialize and create session' ) ) ;
242
237
return ;
243
238
}
244
239
245
- if ( this . session . sampled && this . session . sampled !== 'session' ) {
246
- // If not sampled as session-based, then recording mode will be `buffer`
247
- // Note that we don't explicitly check if `sampled === 'buffer'` because we
248
- // could have sessions from Session storage that are still `error` from
249
- // prior SDK version.
250
- this . recordingMode = 'buffer' ;
240
+ if ( this . session . sampled === false ) {
241
+ // This should only occur if `errorSampleRate` is 0 and was unsampled for
242
+ // session-based replay. In this case there is nothing to do.
243
+ return ;
251
244
}
252
245
246
+ // If segmentId > 0, it means we've previously already captured this session
247
+ // In this case, we still want to continue in `session` recording mode
248
+ this . recordingMode = this . session . sampled === 'buffer' && this . session . segmentId === 0 ? 'buffer' : 'session' ;
249
+
253
250
logInfoNextTick (
254
251
`[Replay] Starting replay in ${ this . recordingMode } mode` ,
255
252
this . _options . _experiments . traceInternals ,
@@ -276,19 +273,20 @@ export class ReplayContainer implements ReplayContainerInterface {
276
273
277
274
logInfoNextTick ( '[Replay] Starting replay in session mode' , this . _options . _experiments . traceInternals ) ;
278
275
279
- const previousSessionId = this . session && this . session . id ;
280
-
281
- const { session } = getSession ( {
282
- timeouts : this . timeouts ,
283
- stickySession : Boolean ( this . _options . stickySession ) ,
284
- currentSession : this . session ,
285
- // This is intentional: create a new session-based replay when calling `start()`
286
- sessionSampleRate : 1 ,
287
- allowBuffering : false ,
288
- traceInternals : this . _options . _experiments . traceInternals ,
289
- } ) ;
276
+ const session = loadOrCreateSession (
277
+ this . session ,
278
+ {
279
+ timeouts : this . timeouts ,
280
+ traceInternals : this . _options . _experiments . traceInternals ,
281
+ } ,
282
+ {
283
+ stickySession : this . _options . stickySession ,
284
+ // This is intentional: create a new session-based replay when calling `start()`
285
+ sessionSampleRate : 1 ,
286
+ allowBuffering : false ,
287
+ } ,
288
+ ) ;
290
289
291
- session . previousSessionId = previousSessionId ;
292
290
this . session = session ;
293
291
294
292
this . _initializeRecording ( ) ;
@@ -305,18 +303,19 @@ export class ReplayContainer implements ReplayContainerInterface {
305
303
306
304
logInfoNextTick ( '[Replay] Starting replay in buffer mode' , this . _options . _experiments . traceInternals ) ;
307
305
308
- const previousSessionId = this . session && this . session . id ;
309
-
310
- const { session } = getSession ( {
311
- timeouts : this . timeouts ,
312
- stickySession : Boolean ( this . _options . stickySession ) ,
313
- currentSession : this . session ,
314
- sessionSampleRate : 0 ,
315
- allowBuffering : true ,
316
- traceInternals : this . _options . _experiments . traceInternals ,
317
- } ) ;
306
+ const session = loadOrCreateSession (
307
+ this . session ,
308
+ {
309
+ timeouts : this . timeouts ,
310
+ traceInternals : this . _options . _experiments . traceInternals ,
311
+ } ,
312
+ {
313
+ stickySession : this . _options . stickySession ,
314
+ sessionSampleRate : 0 ,
315
+ allowBuffering : true ,
316
+ } ,
317
+ ) ;
318
318
319
- session . previousSessionId = previousSessionId ;
320
319
this . session = session ;
321
320
322
321
this . recordingMode = 'buffer' ;
@@ -427,7 +426,7 @@ export class ReplayContainer implements ReplayContainerInterface {
427
426
* new DOM checkout.`
428
427
*/
429
428
public resume ( ) : void {
430
- if ( ! this . _isPaused || ! this . _loadAndCheckSession ( ) ) {
429
+ if ( ! this . _isPaused || ! this . _checkSession ( ) ) {
431
430
return ;
432
431
}
433
432
@@ -535,7 +534,7 @@ export class ReplayContainer implements ReplayContainerInterface {
535
534
if ( ! this . _stopRecording ) {
536
535
// Create a new session, otherwise when the user action is flushed, it
537
536
// will get rejected due to an expired session.
538
- if ( ! this . _loadAndCheckSession ( ) ) {
537
+ if ( ! this . _checkSession ( ) ) {
539
538
return ;
540
539
}
541
540
@@ -634,7 +633,7 @@ export class ReplayContainer implements ReplayContainerInterface {
634
633
635
634
// --- There is recent user activity --- //
636
635
// This will create a new session if expired, based on expiry length
637
- if ( ! this . _loadAndCheckSession ( ) ) {
636
+ if ( ! this . _checkSession ( ) ) {
638
637
return ;
639
638
}
640
639
@@ -751,31 +750,63 @@ export class ReplayContainer implements ReplayContainerInterface {
751
750
752
751
/**
753
752
* Loads (or refreshes) the current session.
753
+ */
754
+ private _initializeSessionForSampling ( ) : void {
755
+ // Whenever there is _any_ error sample rate, we always allow buffering
756
+ // Because we decide on sampling when an error occurs, we need to buffer at all times if sampling for errors
757
+ const allowBuffering = this . _options . errorSampleRate > 0 ;
758
+
759
+ const session = loadOrCreateSession (
760
+ this . session ,
761
+ {
762
+ timeouts : this . timeouts ,
763
+ traceInternals : this . _options . _experiments . traceInternals ,
764
+ } ,
765
+ {
766
+ stickySession : this . _options . stickySession ,
767
+ sessionSampleRate : this . _options . sessionSampleRate ,
768
+ allowBuffering,
769
+ } ,
770
+ ) ;
771
+
772
+ this . session = session ;
773
+ }
774
+
775
+ /**
776
+ * Checks and potentially refreshes the current session.
754
777
* Returns false if session is not recorded.
755
778
*/
756
- private _loadAndCheckSession ( ) : boolean {
757
- const { type, session } = getSession ( {
758
- timeouts : this . timeouts ,
759
- stickySession : Boolean ( this . _options . stickySession ) ,
760
- currentSession : this . session ,
761
- sessionSampleRate : this . _options . sessionSampleRate ,
762
- allowBuffering : this . _options . errorSampleRate > 0 || this . recordingMode === 'buffer' ,
763
- traceInternals : this . _options . _experiments . traceInternals ,
764
- } ) ;
779
+ private _checkSession ( ) : boolean {
780
+ // If there is no session yet, we do not want to refresh anything
781
+ // This should generally not happen, but to be safe....
782
+ if ( ! this . session ) {
783
+ return false ;
784
+ }
785
+
786
+ const currentSession = this . session ;
787
+
788
+ const newSession = maybeRefreshSession (
789
+ currentSession ,
790
+ {
791
+ timeouts : this . timeouts ,
792
+ traceInternals : this . _options . _experiments . traceInternals ,
793
+ } ,
794
+ {
795
+ stickySession : Boolean ( this . _options . stickySession ) ,
796
+ sessionSampleRate : this . _options . sessionSampleRate ,
797
+ allowBuffering : this . _options . errorSampleRate > 0 ,
798
+ } ,
799
+ ) ;
800
+
801
+ const isNew = newSession . id !== currentSession . id ;
765
802
766
803
// If session was newly created (i.e. was not loaded from storage), then
767
804
// enable flag to create the root replay
768
- if ( type === 'new' ) {
805
+ if ( isNew ) {
769
806
this . setInitialState ( ) ;
807
+ this . session = newSession ;
770
808
}
771
809
772
- const currentSessionId = this . getSessionId ( ) ;
773
- if ( session . id !== currentSessionId ) {
774
- session . previousSessionId = currentSessionId ;
775
- }
776
-
777
- this . session = session ;
778
-
779
810
if ( ! this . session . sampled ) {
780
811
void this . stop ( { reason : 'session not refreshed' } ) ;
781
812
return false ;
0 commit comments