Skip to content

Commit 1b4d9da

Browse files
authored
ref(replay): Add jsdoc to all replay modules (#6654)
This is one more step of #6323. Note that this also renames/moves a few things to make more sense.
1 parent e5422c1 commit 1b4d9da

24 files changed

+161
-95
lines changed

docs/event-sending.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ This document gives an outline for how event sending works, and which which plac
7777
## Replay (WIP)
7878

7979
* `replay.sendReplayRequest()`
80-
* `createPayload()`
81-
* `getReplayEvent()`
80+
* `createRecordingData()`
81+
* `prepareReplayEvent()`
8282
* `client._prepareEvent()` (see baseclient)
8383
* `baseclient._applyClientOptions()`
8484
* `baseclient._applyIntegrationsMetadata()`

packages/replay/.eslintrc.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ module.exports = {
2525
rules: {
2626
// TODO (high-prio): Re-enable this after migration
2727
'@typescript-eslint/explicit-member-accessibility': 'off',
28-
// TODO (high-prio): Re-enable this after migration
28+
// Since we target only es6 here, we can leave this off
2929
'@sentry-internal/sdk/no-async-await': 'off',
30-
// TODO (medium-prio): Re-enable this after migration
31-
'jsdoc/require-jsdoc': 'off',
3230
},
3331
},
3432
{

packages/replay/src/coreHandlers/breadcrumbHandler.ts

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import type { InstrumentationTypeBreadcrumb } from '../types';
44
import { DomHandlerData, handleDom } from './handleDom';
55
import { handleScope } from './handleScope';
66

7+
/**
8+
* An event handler to react to breadcrumbs.
9+
*/
710
export function breadcrumbHandler(type: InstrumentationTypeBreadcrumb, handlerData: unknown): Breadcrumb | null {
811
if (type === 'scope') {
912
return handleScope(handlerData as Scope);

packages/replay/src/coreHandlers/handleDom.ts

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export interface DomHandlerData {
99
event: Node | { target: Node };
1010
}
1111

12+
/**
13+
* An event handler to react to DOM events.
14+
*/
1215
export function handleDom(handlerData: DomHandlerData): Breadcrumb | null {
1316
// Taken from https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/integrations/breadcrumbs.ts#L112
1417
let target;

packages/replay/src/coreHandlers/handleFetch.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { ReplayPerformanceEntry } from '../createPerformanceEntry';
2-
import type { ReplayContainer } from '../types';
1+
import type { ReplayContainer, ReplayPerformanceEntry } from '../types';
32
import { createPerformanceSpans } from '../util/createPerformanceSpans';
43
import { shouldFilterRequest } from '../util/shouldFilterRequest';
54

packages/replay/src/coreHandlers/handleHistory.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ReplayPerformanceEntry } from '../createPerformanceEntry';
2-
import type { ReplayContainer } from '../types';
1+
import type { ReplayContainer, ReplayPerformanceEntry } from '../types';
32
import { createPerformanceSpans } from '../util/createPerformanceSpans';
43

54
interface HistoryHandlerData {

packages/replay/src/coreHandlers/handleScope.ts

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { createBreadcrumb } from '../util/createBreadcrumb';
44

55
let _LAST_BREADCRUMB: null | Breadcrumb = null;
66

7+
/**
8+
* An event handler to handle scope changes.
9+
*/
710
export function handleScope(scope: Scope): Breadcrumb | null {
811
const newBreadcrumb = scope.getLastBreadcrumb();
912

packages/replay/src/coreHandlers/handleXhr.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ReplayPerformanceEntry } from '../createPerformanceEntry';
2-
import type { ReplayContainer } from '../types';
1+
import type { ReplayContainer, ReplayPerformanceEntry } from '../types';
32
import { createPerformanceSpans } from '../util/createPerformanceSpans';
43
import { shouldFilterRequest } from '../util/shouldFilterRequest';
54

packages/replay/src/createPerformanceEntry.ts

+16-69
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,12 @@ import { browserPerformanceTimeOrigin } from '@sentry/utils';
22
import { record } from 'rrweb';
33

44
import { WINDOW } from './constants';
5-
import type { AllPerformanceEntry, PerformanceNavigationTiming, PerformancePaintTiming } from './types';
6-
7-
export interface ReplayPerformanceEntry {
8-
/**
9-
* One of these types https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType
10-
*/
11-
type: string;
12-
13-
/**
14-
* A more specific description of the performance entry
15-
*/
16-
name: string;
17-
18-
/**
19-
* The start timestamp in seconds
20-
*/
21-
start: number;
22-
23-
/**
24-
* The end timestamp in seconds
25-
*/
26-
end: number;
27-
28-
/**
29-
* Additional unstructured data to be included
30-
*/
31-
data?: Record<string, unknown>;
32-
}
33-
34-
interface MemoryInfo {
35-
jsHeapSizeLimit: number;
36-
totalJSHeapSize: number;
37-
usedJSHeapSize: number;
38-
}
5+
import type {
6+
AllPerformanceEntry,
7+
PerformanceNavigationTiming,
8+
PerformancePaintTiming,
9+
ReplayPerformanceEntry,
10+
} from './types';
3911

4012
// Map entryType -> function to normalize data for event
4113
// @ts-ignore TODO: entry type does not fit the create* functions entry type
@@ -46,9 +18,12 @@ const ENTRY_TYPES: Record<string, (entry: AllPerformanceEntry) => null | ReplayP
4618
// @ts-ignore TODO: entry type does not fit the create* functions entry type
4719
navigation: createNavigationEntry,
4820
// @ts-ignore TODO: entry type does not fit the create* functions entry type
49-
['largest-contentful-paint']: createLargestContentfulPaint,
21+
'largest-contentful-paint': createLargestContentfulPaint,
5022
};
5123

24+
/**
25+
* Create replay performance entries from the browser performance entries.
26+
*/
5227
export function createPerformanceEntries(entries: AllPerformanceEntry[]): ReplayPerformanceEntry[] {
5328
return entries.map(createPerformanceEntry).filter(Boolean) as ReplayPerformanceEntry[];
5429
}
@@ -67,9 +42,7 @@ function getAbsoluteTime(time: number): number {
6742
return ((browserPerformanceTimeOrigin || WINDOW.performance.timeOrigin) + time) / 1000;
6843
}
6944

70-
// TODO: type definition!
71-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
72-
function createPaintEntry(entry: PerformancePaintTiming) {
45+
function createPaintEntry(entry: PerformancePaintTiming): ReplayPerformanceEntry {
7346
const { duration, entryType, name, startTime } = entry;
7447

7548
const start = getAbsoluteTime(startTime);
@@ -81,9 +54,7 @@ function createPaintEntry(entry: PerformancePaintTiming) {
8154
};
8255
}
8356

84-
// TODO: type definition!
85-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
86-
function createNavigationEntry(entry: PerformanceNavigationTiming) {
57+
function createNavigationEntry(entry: PerformanceNavigationTiming): ReplayPerformanceEntry | null {
8758
// TODO: There looks to be some more interesting bits in here (domComplete, domContentLoaded)
8859
const { entryType, name, duration, domComplete, startTime, transferSize, type } = entry;
8960

@@ -104,9 +75,7 @@ function createNavigationEntry(entry: PerformanceNavigationTiming) {
10475
};
10576
}
10677

107-
// TODO: type definition!
108-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
109-
function createResourceEntry(entry: PerformanceResourceTiming) {
78+
function createResourceEntry(entry: PerformanceResourceTiming): ReplayPerformanceEntry | null {
11079
const { entryType, initiatorType, name, responseEnd, startTime, encodedBodySize, transferSize } = entry;
11180

11281
// Core SDK handles these
@@ -126,9 +95,9 @@ function createResourceEntry(entry: PerformanceResourceTiming) {
12695
};
12796
}
12897

129-
// TODO: type definition!
130-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
131-
function createLargestContentfulPaint(entry: PerformanceEntry & { size: number; element: Node }) {
98+
function createLargestContentfulPaint(
99+
entry: PerformanceEntry & { size: number; element: Node },
100+
): ReplayPerformanceEntry {
132101
const { duration, entryType, startTime, size } = entry;
133102

134103
const start = getAbsoluteTime(startTime);
@@ -147,25 +116,3 @@ function createLargestContentfulPaint(entry: PerformanceEntry & { size: number;
147116
},
148117
};
149118
}
150-
151-
type ReplayMemoryEntry = ReplayPerformanceEntry & { data: { memory: MemoryInfo } };
152-
153-
export function createMemoryEntry(memoryEntry: MemoryInfo): ReplayMemoryEntry {
154-
const { jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize } = memoryEntry;
155-
// we don't want to use `getAbsoluteTime` because it adds the event time to the
156-
// time origin, so we get the current timestamp instead
157-
const time = new Date().getTime() / 1000;
158-
return {
159-
type: 'memory',
160-
name: 'memory',
161-
start: time,
162-
end: time,
163-
data: {
164-
memory: {
165-
jsHeapSizeLimit,
166-
totalJSHeapSize,
167-
usedJSHeapSize,
168-
},
169-
},
170-
};
171-
}

packages/replay/src/eventBuffer.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ interface CreateEventBufferParams {
1212
useCompression: boolean;
1313
}
1414

15+
/**
16+
* Create an event buffer for replays.
17+
*/
1518
export function createEventBuffer({ useCompression }: CreateEventBufferParams): EventBuffer {
1619
// eslint-disable-next-line no-restricted-globals
1720
if (useCompression && window.Worker) {
@@ -72,7 +75,10 @@ class EventBufferArray implements EventBuffer {
7275
}
7376
}
7477

75-
// exporting for testing
78+
/**
79+
* Event buffer that uses a web worker to compress events.
80+
* Exported only for testing.
81+
*/
7682
export class EventBufferCompressionWorker implements EventBuffer {
7783
private _worker: null | Worker;
7884
private _eventBufferItemLength: number = 0;
@@ -90,12 +96,18 @@ export class EventBufferCompressionWorker implements EventBuffer {
9096
return this._eventBufferItemLength;
9197
}
9298

99+
/**
100+
* Destroy the event buffer.
101+
*/
93102
public destroy(): void {
94103
__DEBUG_BUILD__ && logger.log('[Replay] Destroying compression worker');
95104
this._worker?.terminate();
96105
this._worker = null;
97106
}
98107

108+
/**
109+
* Add an event to the event buffer.
110+
*/
99111
public async addEvent(event: RecordingEvent, isCheckout?: boolean): Promise<ReplayRecordingData> {
100112
if (isCheckout) {
101113
// This event is a checkout, make sure worker buffer is cleared before
@@ -110,6 +122,9 @@ export class EventBufferCompressionWorker implements EventBuffer {
110122
return this._sendEventToWorker(event);
111123
}
112124

125+
/**
126+
* Finish the event buffer and return the compressed data.
127+
*/
113128
public finish(): Promise<Uint8Array> {
114129
return this._finishRequest(this._getAndIncrementId());
115130
}
@@ -160,6 +175,9 @@ export class EventBufferCompressionWorker implements EventBuffer {
160175
});
161176
}
162177

178+
/**
179+
* Send the event to the worker.
180+
*/
163181
private _sendEventToWorker(event: RecordingEvent): Promise<ReplayRecordingData> {
164182
const promise = this._postMessage({
165183
id: this._getAndIncrementId(),
@@ -173,6 +191,9 @@ export class EventBufferCompressionWorker implements EventBuffer {
173191
return promise;
174192
}
175193

194+
/**
195+
* Finish the request and return the compressed data from the worker.
196+
*/
176197
private async _finishRequest(id: number): Promise<Uint8Array> {
177198
const promise = this._postMessage({ id, method: 'finish', args: [] });
178199

@@ -182,6 +203,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
182203
return promise as Promise<Uint8Array>;
183204
}
184205

206+
/** Get the current ID and increment it for the next call. */
185207
private _getAndIncrementId(): number {
186208
return this._id++;
187209
}

packages/replay/src/integration.ts

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const MEDIA_SELECTORS = 'img,image,svg,path,rect,area,video,object,picture,embed
1818

1919
let _initialized = false;
2020

21+
/**
22+
* The main replay integration class, to be passed to `init({ integrations: [] })`.
23+
*/
2124
export class Replay implements Integration {
2225
/**
2326
* @inheritDoc
@@ -126,10 +129,12 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
126129
this._isInitialized = true;
127130
}
128131

132+
/** If replay has already been initialized */
129133
protected get _isInitialized(): boolean {
130134
return _initialized;
131135
}
132136

137+
/** Update _isInitialized */
133138
protected set _isInitialized(value: boolean) {
134139
_initialized = value;
135140
}
@@ -181,6 +186,7 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
181186
this._replay.stop();
182187
}
183188

189+
/** Setup the integration. */
184190
private _setup(): void {
185191
// Client is not available in constructor, so we need to wait until setupOnce
186192
this._loadReplayOptionsFromClient();

packages/replay/src/replay.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ import type {
4040
import { addEvent } from './util/addEvent';
4141
import { addMemoryEntry } from './util/addMemoryEntry';
4242
import { createBreadcrumb } from './util/createBreadcrumb';
43-
import { createPayload } from './util/createPayload';
4443
import { createPerformanceSpans } from './util/createPerformanceSpans';
44+
import { createRecordingData } from './util/createRecordingData';
4545
import { createReplayEnvelope } from './util/createReplayEnvelope';
4646
import { debounce } from './util/debounce';
47-
import { getReplayEvent } from './util/getReplayEvent';
4847
import { isExpired } from './util/isExpired';
4948
import { isSessionExpired } from './util/isSessionExpired';
5049
import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/monkeyPatchRecordDroppedEvent';
50+
import { prepareReplayEvent } from './util/prepareReplayEvent';
5151

5252
/**
5353
* Returns true to return control to calling function, otherwise continue with normal batching
@@ -56,6 +56,9 @@ import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/m
5656
const BASE_RETRY_INTERVAL = 5000;
5757
const MAX_RETRY_COUNT = 3;
5858

59+
/**
60+
* The main replay container class, which holds all the state and methods for recording and sending replays.
61+
*/
5962
export class ReplayContainer implements ReplayContainerInterface {
6063
public eventBuffer: EventBuffer | null = null;
6164

@@ -904,7 +907,7 @@ export class ReplayContainer implements ReplayContainerInterface {
904907
includeReplayStartTimestamp,
905908
eventContext,
906909
}: SendReplay): Promise<void | TransportMakeRequestResponse> {
907-
const payloadWithSequence = createPayload({
910+
const recordingData = createRecordingData({
908911
events,
909912
headers: {
910913
segment_id,
@@ -938,7 +941,7 @@ export class ReplayContainer implements ReplayContainerInterface {
938941
replay_type: this.session.sampled,
939942
};
940943

941-
const replayEvent = await getReplayEvent({ scope, client, replayId, event: baseEvent });
944+
const replayEvent = await prepareReplayEvent({ scope, client, replayId, event: baseEvent });
942945

943946
if (!replayEvent) {
944947
// Taken from baseclient's `_processEvent` method, where this is handled for errors/transactions
@@ -989,7 +992,7 @@ export class ReplayContainer implements ReplayContainerInterface {
989992
}
990993
*/
991994

992-
const envelope = createReplayEnvelope(replayEvent, payloadWithSequence, dsn, client.getOptions().tunnel);
995+
const envelope = createReplayEnvelope(replayEvent, recordingData, dsn, client.getOptions().tunnel);
993996

994997
try {
995998
return await transport.send(envelope);
@@ -998,6 +1001,9 @@ export class ReplayContainer implements ReplayContainerInterface {
9981001
}
9991002
}
10001003

1004+
/**
1005+
* Reset the counter of retries for sending replays.
1006+
*/
10011007
resetRetries(): void {
10021008
this._retryCount = 0;
10031009
this._retryInterval = BASE_RETRY_INTERVAL;

packages/replay/src/session/saveSession.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { REPLAY_SESSION_KEY, WINDOW } from '../constants';
22
import type { Session } from '../types';
33

4+
/**
5+
* Save a session to session storage.
6+
*/
47
export function saveSession(session: Session): void {
58
const hasSessionStorage = 'sessionStorage' in WINDOW;
69
if (!hasSessionStorage) {

0 commit comments

Comments
 (0)