@@ -18,7 +18,8 @@ import { handleKeyboardEvent } from './coreHandlers/handleKeyboardEvent';
1818import { setupPerformanceObserver } from './coreHandlers/performanceObserver' ;
1919import { createEventBuffer } from './eventBuffer' ;
2020import { clearSession } from './session/clearSession' ;
21- import { getSession } from './session/getSession' ;
21+ import { loadOrCreateSession } from './session/loadOrCreateSession' ;
22+ import { maybeRefreshSession } from './session/maybeRefreshSession' ;
2223import { saveSession } from './session/saveSession' ;
2324import type {
2425 AddEventResult ,
@@ -228,28 +229,24 @@ export class ReplayContainer implements ReplayContainerInterface {
228229
229230 // Otherwise if there is _any_ sample rate set, try to load an existing
230231 // 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 ( ) ;
238233
239234 if ( ! this . session ) {
240235 // This should not happen, something wrong has occurred
241236 this . _handleException ( new Error ( 'Unable to initialize and create session' ) ) ;
242237 return ;
243238 }
244239
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 ;
251244 }
252245
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+
253250 logInfoNextTick (
254251 `[Replay] Starting replay in ${ this . recordingMode } mode` ,
255252 this . _options . _experiments . traceInternals ,
@@ -276,19 +273,20 @@ export class ReplayContainer implements ReplayContainerInterface {
276273
277274 logInfoNextTick ( '[Replay] Starting replay in session mode' , this . _options . _experiments . traceInternals ) ;
278275
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+ ) ;
290289
291- session . previousSessionId = previousSessionId ;
292290 this . session = session ;
293291
294292 this . _initializeRecording ( ) ;
@@ -305,18 +303,19 @@ export class ReplayContainer implements ReplayContainerInterface {
305303
306304 logInfoNextTick ( '[Replay] Starting replay in buffer mode' , this . _options . _experiments . traceInternals ) ;
307305
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+ ) ;
318318
319- session . previousSessionId = previousSessionId ;
320319 this . session = session ;
321320
322321 this . recordingMode = 'buffer' ;
@@ -427,7 +426,7 @@ export class ReplayContainer implements ReplayContainerInterface {
427426 * new DOM checkout.`
428427 */
429428 public resume ( ) : void {
430- if ( ! this . _isPaused || ! this . _loadAndCheckSession ( ) ) {
429+ if ( ! this . _isPaused || ! this . _checkSession ( ) ) {
431430 return ;
432431 }
433432
@@ -535,7 +534,7 @@ export class ReplayContainer implements ReplayContainerInterface {
535534 if ( ! this . _stopRecording ) {
536535 // Create a new session, otherwise when the user action is flushed, it
537536 // will get rejected due to an expired session.
538- if ( ! this . _loadAndCheckSession ( ) ) {
537+ if ( ! this . _checkSession ( ) ) {
539538 return ;
540539 }
541540
@@ -634,7 +633,7 @@ export class ReplayContainer implements ReplayContainerInterface {
634633
635634 // --- There is recent user activity --- //
636635 // This will create a new session if expired, based on expiry length
637- if ( ! this . _loadAndCheckSession ( ) ) {
636+ if ( ! this . _checkSession ( ) ) {
638637 return ;
639638 }
640639
@@ -751,31 +750,63 @@ export class ReplayContainer implements ReplayContainerInterface {
751750
752751 /**
753752 * 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.
754777 * Returns false if session is not recorded.
755778 */
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 ;
765802
766803 // If session was newly created (i.e. was not loaded from storage), then
767804 // enable flag to create the root replay
768- if ( type === 'new' ) {
805+ if ( isNew ) {
769806 this . setInitialState ( ) ;
807+ this . session = newSession ;
770808 }
771809
772- const currentSessionId = this . getSessionId ( ) ;
773- if ( session . id !== currentSessionId ) {
774- session . previousSessionId = currentSessionId ;
775- }
776-
777- this . session = session ;
778-
779810 if ( ! this . session . sampled ) {
780811 void this . stop ( { reason : 'session not refreshed' } ) ;
781812 return false ;
0 commit comments