Skip to content

Commit fd6649f

Browse files
committed
ref(replay): Extract addEvent out
1 parent d30c659 commit fd6649f

File tree

6 files changed

+67
-56
lines changed

6 files changed

+67
-56
lines changed

packages/replay/src/replay.ts

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { createPayload } from './util/createPayload';
4141
import { isExpired } from './util/isExpired';
4242
import { isSessionExpired } from './util/isSessionExpired';
4343
import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/monkeyPatchRecordDroppedEvent';
44+
import { addEvent } from './util/addEvent';
4445

4546
/**
4647
* Returns true to return control to calling function, otherwise continue with normal batching
@@ -137,6 +138,11 @@ export class ReplayContainer {
137138
return this._isEnabled;
138139
}
139140

141+
/** If recording is currently paused. */
142+
public isPaused(): boolean {
143+
return this._isPaused;
144+
}
145+
140146
/**
141147
* Initializes the plugin.
142148
*
@@ -439,7 +445,7 @@ export class ReplayContainer {
439445

440446
// We need to clear existing events on a checkout, otherwise they are
441447
// incremental event updates and should be appended
442-
this.addEvent(event, isCheckout);
448+
addEvent(this, event, isCheckout);
443449

444450
// Different behavior for full snapshots (type=2), ignore other event types
445451
// See https://github.com/rrweb-io/rrweb/blob/d8f9290ca496712aa1e7d472549480c4e7876594/packages/rrweb/src/types.ts#L16
@@ -553,7 +559,7 @@ export class ReplayContainer {
553559
}
554560

555561
this.addUpdate(() => {
556-
this.addEvent({
562+
addEvent(this, {
557563
type: EventType.Custom,
558564
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
559565
// but maybe we should just keep them as milliseconds
@@ -623,45 +629,6 @@ export class ReplayContainer {
623629
record.takeFullSnapshot(true);
624630
}
625631

626-
/**
627-
* Add an event to the event buffer
628-
*/
629-
addEvent(event: RecordingEvent, isCheckout?: boolean): void {
630-
if (!this.eventBuffer) {
631-
// This implies that `_isEnabled` is false
632-
return;
633-
}
634-
635-
if (this._isPaused) {
636-
// Do not add to event buffer when recording is paused
637-
return;
638-
}
639-
640-
// TODO: sadness -- we will want to normalize timestamps to be in ms -
641-
// requires coordination with frontend
642-
const isMs = event.timestamp > 9999999999;
643-
const timestampInMs = isMs ? event.timestamp : event.timestamp * 1000;
644-
645-
// Throw out events that happen more than 5 minutes ago. This can happen if
646-
// page has been left open and idle for a long period of time and user
647-
// comes back to trigger a new session. The performance entries rely on
648-
// `performance.timeOrigin`, which is when the page first opened.
649-
if (timestampInMs + SESSION_IDLE_DURATION < new Date().getTime()) {
650-
return;
651-
}
652-
653-
// Only record earliest event if a new session was created, otherwise it
654-
// shouldn't be relevant
655-
if (
656-
this.session?.segmentId === 0 &&
657-
(!this._context.earliestEvent || timestampInMs < this._context.earliestEvent)
658-
) {
659-
this._context.earliestEvent = timestampInMs;
660-
}
661-
662-
this.eventBuffer.addEvent(event, isCheckout);
663-
}
664-
665632
/**
666633
* Update user activity (across session lifespans)
667634
*/
@@ -710,7 +677,7 @@ export class ReplayContainer {
710677
*/
711678
createCustomBreadcrumb(breadcrumb: Breadcrumb): void {
712679
this.addUpdate(() => {
713-
this.addEvent({
680+
addEvent(this, {
714681
type: EventType.Custom,
715682
timestamp: breadcrumb.timestamp || 0,
716683
data: {
@@ -727,7 +694,7 @@ export class ReplayContainer {
727694
createPerformanceSpans(entries: ReplayPerformanceEntry[]): Promise<void[]> {
728695
return Promise.all(
729696
entries.map(({ type, start, end, name, data }) =>
730-
this.addEvent({
697+
addEvent(this, {
731698
type: EventType.Custom,
732699
timestamp: start,
733700
data: {

packages/replay/src/util/addEvent.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { SESSION_IDLE_DURATION } from '../constants';
2+
import { ReplayContainer } from '../replay';
3+
import { RecordingEvent } from '../types';
4+
5+
/**
6+
* Add an event to the event buffer
7+
*/
8+
export function addEvent(replay: ReplayContainer, event: RecordingEvent, isCheckout?: boolean): void {
9+
if (!replay.eventBuffer) {
10+
// This implies that `_isEnabled` is false
11+
return;
12+
}
13+
14+
if (replay.isPaused()) {
15+
// Do not add to event buffer when recording is paused
16+
return;
17+
}
18+
19+
// TODO: sadness -- we will want to normalize timestamps to be in ms -
20+
// requires coordination with frontend
21+
const isMs = event.timestamp > 9999999999;
22+
const timestampInMs = isMs ? event.timestamp : event.timestamp * 1000;
23+
24+
// Throw out events that happen more than 5 minutes ago. This can happen if
25+
// page has been left open and idle for a long period of time and user
26+
// comes back to trigger a new session. The performance entries rely on
27+
// `performance.timeOrigin`, which is when the page first opened.
28+
if (timestampInMs + SESSION_IDLE_DURATION < new Date().getTime()) {
29+
return;
30+
}
31+
32+
// Only record earliest event if a new session was created, otherwise it
33+
// shouldn't be relevant
34+
const earliestEvent = replay.getContext().earliestEvent;
35+
if (replay.session?.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
36+
replay.getContext().earliestEvent = timestampInMs;
37+
}
38+
39+
replay.eventBuffer.addEvent(event, isCheckout);
40+
}

packages/replay/test/unit/index-errorSampleRate.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ jest.unmock('@sentry/browser');
33
import { captureException } from '@sentry/browser';
44

55
import { REPLAY_SESSION_KEY, VISIBILITY_CHANGE_TIMEOUT, WINDOW } from '../../src/constants';
6+
import { addEvent } from '../../src/util/addEvent';
67
import { ReplayContainer } from './../../src/replay';
78
import { PerformanceEntryResource } from './../fixtures/performanceEntry/resource';
89
import { BASE_TIMESTAMP, RecordMock } from './../index';
@@ -195,7 +196,7 @@ describe('Replay (errorSampleRate)', () => {
195196
jest.advanceTimersByTime(ELAPSED);
196197

197198
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 };
198-
replay.addEvent(TEST_EVENT);
199+
addEvent(replay, TEST_EVENT);
199200

200201
document.dispatchEvent(new Event('visibilitychange'));
201202

packages/replay/test/unit/index-noSticky.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Transport } from '@sentry/types';
33
import * as SentryUtils from '@sentry/utils';
44

55
import { SESSION_IDLE_DURATION, VISIBILITY_CHANGE_TIMEOUT } from '../../src/constants';
6+
import { addEvent } from '../../src/util/addEvent';
67
import { ReplayContainer } from './../../src/replay';
78
import { BASE_TIMESTAMP, mockRrweb, mockSdk } from './../index';
89
import { useFakeTimers } from './../utils/use-fake-timers';
@@ -119,7 +120,7 @@ describe('Replay (no sticky)', () => {
119120
jest.advanceTimersByTime(ELAPSED);
120121

121122
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 };
122-
replay.addEvent(TEST_EVENT);
123+
addEvent(replay, TEST_EVENT);
123124

124125
document.dispatchEvent(new Event('visibilitychange'));
125126

packages/replay/test/unit/index.test.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { EventType } from 'rrweb';
77
import { MAX_SESSION_LIFE, REPLAY_SESSION_KEY, VISIBILITY_CHANGE_TIMEOUT, WINDOW } from '../../src/constants';
88
import { ReplayContainer } from '../../src/replay';
99
import { RecordingEvent } from '../../src/types';
10+
import { addEvent } from '../../src/util/addEvent';
1011
import { useFakeTimers } from '../utils/use-fake-timers';
1112
import { PerformanceEntryResource } from './../fixtures/performanceEntry/resource';
1213
import { BASE_TIMESTAMP, RecordMock } from './../index';
@@ -82,7 +83,7 @@ describe('Replay with custom mock', () => {
8283
timestamp: new Date().valueOf(),
8384
} as RecordingEvent;
8485

85-
replay.addEvent(event);
86+
addEvent(replay, event);
8687

8788
await replay.runFlush();
8889

@@ -250,7 +251,7 @@ describe('Replay', () => {
250251
},
251252
};
252253

253-
replay.addEvent(TEST_EVENT);
254+
addEvent(replay, TEST_EVENT);
254255
WINDOW.dispatchEvent(new Event('blur'));
255256
await new Promise(process.nextTick);
256257
expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled();
@@ -276,7 +277,7 @@ describe('Replay', () => {
276277

277278
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 };
278279

279-
replay.addEvent(TEST_EVENT);
280+
addEvent(replay, TEST_EVENT);
280281
document.dispatchEvent(new Event('visibilitychange'));
281282
jest.runAllTimers();
282283
await new Promise(process.nextTick);
@@ -687,15 +688,15 @@ describe('Replay', () => {
687688

688689
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 2 };
689690

690-
replay.addEvent(TEST_EVENT);
691+
addEvent(replay, TEST_EVENT);
691692
WINDOW.dispatchEvent(new Event('blur'));
692693
await new Promise(process.nextTick);
693694
expect(replay).toHaveSentReplay({
694695
recordingPayloadHeader: { segment_id: 0 },
695696
});
696697
expect(replay.session?.segmentId).toBe(1);
697698

698-
replay.addEvent(TEST_EVENT);
699+
addEvent(replay, TEST_EVENT);
699700
WINDOW.dispatchEvent(new Event('blur'));
700701
jest.runAllTimers();
701702
await new Promise(process.nextTick);
@@ -727,7 +728,7 @@ describe('Replay', () => {
727728
type: 2,
728729
};
729730

730-
replay.addEvent(TEST_EVENT);
731+
addEvent(replay, TEST_EVENT);
731732
WINDOW.dispatchEvent(new Event('blur'));
732733
await new Promise(process.nextTick);
733734

@@ -812,10 +813,10 @@ describe('Replay', () => {
812813
type: 2,
813814
};
814815

815-
replay.addEvent(TEST_EVENT);
816+
addEvent(replay, TEST_EVENT);
816817

817818
// Add a fake event that started BEFORE
818-
replay.addEvent({
819+
addEvent(replay, {
819820
data: {},
820821
timestamp: (BASE_TIMESTAMP - 10000) / 1000,
821822
type: 5,
@@ -861,7 +862,7 @@ describe('Replay', () => {
861862
type: 2,
862863
};
863864

864-
replay.addEvent(TEST_EVENT);
865+
addEvent(replay, TEST_EVENT);
865866
// This event will trigger a flush
866867
WINDOW.dispatchEvent(new Event('blur'));
867868
jest.runAllTimers();

packages/replay/test/unit/stop.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as SentryUtils from '@sentry/utils';
22

33
import { SESSION_IDLE_DURATION, WINDOW } from '../../src/constants';
44
import { ReplayContainer } from '../../src/replay';
5+
import { addEvent } from '../../src/util/addEvent';
56
import { Replay } from './../../src';
67
// mock functions need to be imported first
78
import { BASE_TIMESTAMP, mockRrweb, mockSdk } from './../index';
@@ -73,7 +74,7 @@ describe('Replay - stop', () => {
7374
// Pretend 5 seconds have passed
7475
jest.advanceTimersByTime(ELAPSED);
7576

76-
replay.addEvent(TEST_EVENT);
77+
addEvent(replay, TEST_EVENT);
7778
WINDOW.dispatchEvent(new Event('blur'));
7879
await new Promise(process.nextTick);
7980
expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled();
@@ -103,7 +104,7 @@ describe('Replay - stop', () => {
103104
},
104105
};
105106

106-
replay.addEvent(TEST_EVENT);
107+
addEvent(replay, TEST_EVENT);
107108
WINDOW.dispatchEvent(new Event('blur'));
108109
jest.runAllTimers();
109110
await new Promise(process.nextTick);

0 commit comments

Comments
 (0)