Conversation
If a user has not performed any user activity for MAX_SESSION_LIFE (30 minutes currently), stop dom recording until a user performs an action (currently: mouse click, navigation, tab focus). Previously, dom recording would trigger new sessions indefinitely.
size-limit report 📦
|
| import { record } from 'rrweb'; | ||
|
|
||
| import createBreadcrumb from '../util/createBreadcrumb'; | ||
| import { createBreadcrumb } from '../util/createBreadcrumb'; |
| /** | ||
| * We want to batch uploads of replay events. Save events only if | ||
| * `<flushMinDelay>` milliseconds have elapsed since the last event | ||
| * *OR* if `<flushMaxDelay>` milliseconds have elapsed. | ||
| * | ||
| * Accepts a callback to perform side-effects and returns true to stop batch | ||
| * processing and hand back control to caller. | ||
| */ | ||
| addUpdate(cb?: AddUpdateCallback) { | ||
| // We need to always run `cb` (e.g. in the case of captureOnlyOnError == true) | ||
| const cbResult = cb?.(); | ||
|
|
||
| // If this option is turned on then we will only want to call `flush` | ||
| // explicitly | ||
| if (this.options.captureOnlyOnError) { | ||
| return; | ||
| } | ||
|
|
||
| // If callback is true, we do not want to continue with flushing -- the | ||
| // caller will need to handle it. | ||
| if (cbResult === true) { | ||
| return; | ||
| } | ||
|
|
||
| // addUpdate is called quite frequently - use debouncedFlush so that it | ||
| // respects the flush delays and does not flush immediately | ||
| this.debouncedFlush(); | ||
| } | ||
|
|
| this.loadSession({ expiry: VISIBILITY_CHANGE_TIMEOUT }); | ||
| this.triggerFullSnapshot(); |
There was a problem hiding this comment.
This is replaced by checkAndHandleExpiredSession call.
src/index.ts
Outdated
| if (updateUserActivity) { | ||
| this.lastActivity = new Date().getTime(); | ||
| } | ||
|
|
||
| // Prevent starting a new session if the last user activity is older than | ||
| // MAX_SESSION_LIFE. Otherwise non-user activity can trigger a new | ||
| // session+recording. This creates noisy replays that do not have much | ||
| // content in them. | ||
| if (this.lastActivity && isExpired(this.lastActivity, MAX_SESSION_LIFE)) { | ||
| // We should stop recording emitter if it exists | ||
| if (this.stopRecording) { | ||
| this.stopRecording(); | ||
| this.stopRecording = undefined; | ||
| } | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| // --- There is recent user activity --- // | ||
|
|
||
| // Ensure that recording is resumed | ||
| if (!this.stopRecording) { | ||
| this.startRecording(); | ||
| } |
There was a problem hiding this comment.
Basically the bulk of the change.
src/index.ts
Outdated
| } | ||
|
|
||
| if (result.category === 'ui.click') { | ||
| this.checkAndHandleExpiredSession({ updateUserActivity: true }); |
There was a problem hiding this comment.
I think this actually fixes a bug where we update the session last activity without checking if it's expired yet. This means we could extend beyond the 5 minute expiry.
src/index.ts
Outdated
|
|
||
| // Ensure that recording is resumed | ||
| if (!this.stopRecording) { | ||
| this.startRecording(); |
There was a problem hiding this comment.
This actually caused an infinite loop since it would trigger a fullsnapshot, and eventually back into this function. I've added an intermediate "paused" state to handle this.
src/index.ts
Outdated
| this.checkAndHandleExpiredSession({ updateUserActivity: true }); | ||
| this.updateLastActivity(); |
There was a problem hiding this comment.
Refactored this a bit so we don't end up in a cycle
| if (this.isPaused) { | ||
| // Do not add to event buffer when recording is paused | ||
| return; | ||
| } | ||
|
|
There was a problem hiding this comment.
This is to handle a separate bug I found. The core SDK event listeners were adding to the eventBuffer which was not being cleared on new DOM checkouts, so it was possible to have stale events in here. Now when a session goes idle, we do not add to event buffer at all.
|
Found a bug with the session idle pause/resume logic so had to make some changes. |
src/index.ts
Outdated
| // Create a new session, otherwise when the user action is flushed, it will get rejected due to an expired session. | ||
| this.loadSession({ expiry: SESSION_IDLE_DURATION }); | ||
|
|
||
| // Note: This will cause a new checkout |
There was a problem hiding this comment.
guaranteed to start a new checkout? or will it do so only if needed
If a user has not performed any user activity for MAX_SESSION_LIFE (30 minutes currently), stop dom recording until a user performs an action (currently: mouse click, navigation, tab focus). Previously, dom recording would trigger new sessions indefinitely. Fixes getsentry/sentry-replay#204
If a user has not performed any user activity for MAX_SESSION_LIFE (30 minutes currently), stop dom recording until a user performs an action (currently: mouse click, navigation, tab focus).
Previously, dom recording would trigger new sessions indefinitely.
Fixes #204