From 4a983eb00bc8460f7b221b35282902b83d720669 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 27 Jan 2024 14:07:28 +0000 Subject: [PATCH] full snapshots 5 minutes apart --- .../replay/sessionrecording.test.ts | 21 ++++++++++++++++++ src/extensions/replay/sessionrecording.ts | 22 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/__tests__/extensions/replay/sessionrecording.test.ts b/src/__tests__/extensions/replay/sessionrecording.test.ts index 5d6e21c8c..8ba67e05b 100644 --- a/src/__tests__/extensions/replay/sessionrecording.test.ts +++ b/src/__tests__/extensions/replay/sessionrecording.test.ts @@ -1484,4 +1484,25 @@ describe('SessionRecording', () => { expect(sessionRecording['rrwebRecord']).not.toBeUndefined() }) }) + + describe('scheduled full snapshots', () => { + it('starts out unscheduled', () => { + expect(sessionRecording['_fullSnapshotTimer']).toBe(undefined) + }) + + it('schedules a snapshot on start', () => { + sessionRecording.startRecordingIfEnabled() + expect(sessionRecording['_fullSnapshotTimer']).not.toBe(undefined) + }) + + it('reschedules a snapshot, when we take a full snapshot', () => { + sessionRecording.startRecordingIfEnabled() + const startTimer = sessionRecording['_fullSnapshotTimer'] + + _emit(createFullSnapshot()) + + expect(sessionRecording['_fullSnapshotTimer']).not.toBe(undefined) + expect(sessionRecording['_fullSnapshotTimer']).not.toBe(startTimer) + }) + }) }) diff --git a/src/extensions/replay/sessionrecording.ts b/src/extensions/replay/sessionrecording.ts index 8620bf37d..0c68ff065 100644 --- a/src/extensions/replay/sessionrecording.ts +++ b/src/extensions/replay/sessionrecording.ts @@ -119,6 +119,8 @@ export class SessionRecording { private _canvasFps: number | null = null private _canvasQuality: number | null = null + private _fullSnapshotTimer?: number + // Util to help developers working on this feature manually override _forceAllowLocalhostNetworkCapture = false @@ -575,6 +577,11 @@ export class SessionRecording { }, }) + // rrweb takes a snapshot on initialization, + // but we want to take one in five minutes + // if nothing else happens to reset the timer + this._scheduleFullSnapshot() + const activePlugins = this._gatherRRWebPlugins() this.stopRrweb = this.rrwebRecord({ emit: (event) => { @@ -612,6 +619,16 @@ export class SessionRecording { }) } + private _scheduleFullSnapshot(): void { + if (this._fullSnapshotTimer) { + clearInterval(this._fullSnapshotTimer) + } + + this._fullSnapshotTimer = setInterval(() => { + this._tryTakeFullSnapshot() + }, 1000 * 60 * 5) // 5 minutes + } + private _gatherRRWebPlugins() { const plugins: RecordPlugin[] = [] @@ -651,6 +668,11 @@ export class SessionRecording { rawEvent.data.href = href } + if (rawEvent.type === EventType.FullSnapshot) { + // we're processing a full snapshot, so we should reset the timer + this._scheduleFullSnapshot() + } + const throttledEvent = this.mutationRateLimiter ? this.mutationRateLimiter.throttleMutations(rawEvent) : rawEvent