Skip to content

Commit 3ed030d

Browse files
committed
refactor out integrations abstraction
1 parent 2f2ef5f commit 3ed030d

File tree

9 files changed

+54
-39
lines changed

9 files changed

+54
-39
lines changed

dev-packages/browser-integration-tests/suites/replay/canvas/withCanvasIntegrationFirst/test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { expect } from '@playwright/test';
2-
import type { ReplayCanvasIntegrationOptions } from '@sentry-internal/replay-canvas';
32

43
import { sentryTest } from '../../../../utils/fixtures';
54
import { getReplaySnapshot, shouldSkipReplayTest } from '../../../../utils/replayHelpers';
@@ -22,8 +21,8 @@ sentryTest('sets up canvas when adding ReplayCanvas integration first', async ({
2221
await page.goto(url);
2322

2423
const replay = await getReplaySnapshot(page);
25-
const canvasOptions = replay._integrations.canvas as ReplayCanvasIntegrationOptions;
26-
expect(canvasOptions.sampling.canvas).toBe(2);
27-
expect(canvasOptions.dataURLOptions.quality).toBe(0.4);
24+
const canvasOptions = replay._canvas;
25+
expect(canvasOptions?.sampling.canvas).toBe(2);
26+
expect(canvasOptions?.dataURLOptions.quality).toBe(0.4);
2827
expect(replay._hasCanvas).toBe(true);
2928
});

dev-packages/browser-integration-tests/suites/replay/canvas/withCanvasIntegrationSecond/test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { expect } from '@playwright/test';
2-
import type { ReplayCanvasIntegrationOptions } from '@sentry-internal/replay-canvas';
32

43
import { sentryTest } from '../../../../utils/fixtures';
54
import { getReplaySnapshot, shouldSkipReplayTest } from '../../../../utils/replayHelpers';
@@ -22,8 +21,8 @@ sentryTest('sets up canvas when adding ReplayCanvas integration after Replay', a
2221
await page.goto(url);
2322

2423
const replay = await getReplaySnapshot(page);
25-
const canvasOptions = replay._integrations.canvas as ReplayCanvasIntegrationOptions;
26-
expect(canvasOptions.sampling.canvas).toBe(2);
27-
expect(canvasOptions.dataURLOptions.quality).toBe(0.4);
24+
const canvasOptions = replay._canvas;
25+
expect(canvasOptions?.sampling.canvas).toBe(2);
26+
expect(canvasOptions?.dataURLOptions.quality).toBe(0.4);
2827
expect(replay._hasCanvas).toBe(true);
2928
});

dev-packages/browser-integration-tests/suites/replay/canvas/withoutCanvasIntegration/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ sentryTest('does not setup up canvas without ReplayCanvas integration', async ({
2121
await page.goto(url);
2222

2323
const replay = await getReplaySnapshot(page);
24-
const canvasOptions = replay._integrations.canvas;
24+
const canvasOptions = replay._canvas;
2525
expect(canvasOptions).toBe(undefined);
2626
expect(replay._hasCanvas).toBe(false);
2727
});

dev-packages/browser-integration-tests/utils/replayHelpers.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* eslint-disable max-lines */
2+
import { ReplayCanvasIntegrationOptions } from '@sentry-internal/replay-canvas';
23
import type { fullSnapshotEvent, incrementalSnapshotEvent } from '@sentry-internal/rrweb';
34
import { EventType } from '@sentry-internal/rrweb';
45
import type { ReplayEventWithTime } from '@sentry/browser';
@@ -174,23 +175,27 @@ export function getReplaySnapshot(page: Page): Promise<{
174175
_isEnabled: boolean;
175176
_context: InternalEventContext;
176177
_options: ReplayPluginOptions;
177-
_integrations: Record<string, unknown>;
178+
_canvas: ReplayCanvasIntegrationOptions | undefined;
178179
_hasCanvas: boolean;
179180
session: Session | undefined;
180181
recordingMode: ReplayRecordingMode;
181182
}> {
182183
return page.evaluate(() => {
183-
const replayIntegration = (window as unknown as Window & { Replay: { _replay: ReplayContainer } }).Replay;
184+
const replayIntegration = (
185+
window as unknown as Window & {
186+
Replay: { _replay: ReplayContainer & { _canvas: ReplayCanvasIntegrationOptions | undefined } };
187+
}
188+
).Replay;
184189
const replay = replayIntegration._replay;
185190

186191
const replaySnapshot = {
187192
_isPaused: replay.isPaused(),
188193
_isEnabled: replay.isEnabled(),
189194
_context: replay.getContext(),
190195
_options: replay.getOptions(),
191-
_integrations: replay.getIntegrations(),
196+
_canvas: replay['_canvas'],
192197
// We cannot pass the function through as this is serialized
193-
_hasCanvas: typeof replay.getIntegrations().canvas?.getCanvasManager === 'function',
198+
_hasCanvas: typeof replay['_canvas']?.getCanvasManager === 'function',
194199
session: replay.session,
195200
recordingMode: replay.recordingMode,
196201
};

packages/replay-canvas/src/canvas.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CanvasManager } from '@sentry-internal/rrweb';
22
import { convertIntegrationFnToClass } from '@sentry/core';
33
import type { CanvasManagerInterface } from '@sentry/replay';
4-
import { IntegrationFn } from '@sentry/types';
4+
import type { IntegrationFn } from '@sentry/types';
55

66
interface ReplayCanvasOptions {
77
quality: 'low' | 'medium' | 'high';
@@ -69,8 +69,8 @@ const replayCanvasIntegration = ((options: Partial<ReplayCanvasOptions> = {}) =>
6969
getCanvasManager: (options: ConstructorParameters<typeof CanvasManager>[0]) => new CanvasManager(options),
7070
...(CANVAS_QUALITY[quality || 'medium'] || CANVAS_QUALITY.medium),
7171
};
72-
}
72+
},
7373
};
7474
}) satisfies IntegrationFn;
7575

76-
export const ReplayCanvasIntegration = convertIntegrationFnToClass(replayCanvasIntegration, INTEGRATION_NAME);
76+
export const ReplayCanvas = convertIntegrationFnToClass(INTEGRATION_NAME, replayCanvasIntegration);

packages/replay/src/integration.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ import {
1010
MIN_REPLAY_DURATION_LIMIT,
1111
} from './constants';
1212
import { ReplayContainer } from './replay';
13-
import type { RecordingOptions, ReplayConfiguration, ReplayPluginOptions, SendBufferedReplayOptions } from './types';
13+
import type {
14+
RecordingOptions,
15+
ReplayCanvasIntegrationOptions,
16+
ReplayConfiguration,
17+
ReplayPluginOptions,
18+
SendBufferedReplayOptions,
19+
} from './types';
1420
import { getPrivacyOptions } from './util/getPrivacyOptions';
1521
import { maskAttribute } from './util/maskAttribute';
1622

@@ -355,13 +361,13 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
355361
try {
356362
const client = getClient()!;
357363
const canvasIntegration = client.getIntegrationById!('ReplayCanvas') as Integration & {
358-
getOptions(): Partial<ReplayConfiguration>;
364+
getOptions(): ReplayCanvasIntegrationOptions;
359365
};
360366
if (!canvasIntegration) {
361367
return;
362368
}
363369

364-
this._replay!.addIntegration('canvas', canvasIntegration.getOptions());
370+
this._replay!['_canvas'] = canvasIntegration.getOptions();
365371
} catch {
366372
// ignore errors here
367373
}

packages/replay/src/replay.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type {
3838
RecordingEvent,
3939
RecordingOptions,
4040
ReplayBreadcrumbFrame,
41+
ReplayCanvasIntegrationOptions,
4142
ReplayContainer as ReplayContainerInterface,
4243
ReplayPerformanceEntry,
4344
ReplayPluginOptions,
@@ -145,9 +146,9 @@ export class ReplayContainer implements ReplayContainerInterface {
145146
private _context: InternalEventContext;
146147

147148
/**
148-
* Internal integrations (e.g. canvas)
149+
* Internal use for canvas recording options
149150
*/
150-
private _integrations: Record<string, Record<string, unknown>>;
151+
private _canvas: ReplayCanvasIntegrationOptions | undefined;
151152

152153
public constructor({
153154
options,
@@ -167,7 +168,6 @@ export class ReplayContainer implements ReplayContainerInterface {
167168
this._lastActivity = Date.now();
168169
this._isEnabled = false;
169170
this._isPaused = false;
170-
this._integrations = {};
171171
this._hasInitializedCoreListeners = false;
172172
this._context = {
173173
errorIds: new Set(),
@@ -228,11 +228,6 @@ export class ReplayContainer implements ReplayContainerInterface {
228228
return this._options;
229229
}
230230

231-
/** Get the replay integrations. [test only] */
232-
public getIntegrations(): Record<string, Record<string, unknown>> {
233-
return { ...this._integrations };
234-
}
235-
236231
/**
237232
* Initializes the plugin based on sampling configuration. Should not be
238233
* called outside of constructor.
@@ -348,7 +343,7 @@ export class ReplayContainer implements ReplayContainerInterface {
348343
*/
349344
public startRecording(): void {
350345
try {
351-
const { canvas } = this._integrations;
346+
const canvasOptions = this._canvas;
352347

353348
this._stopRecording = record({
354349
...this._recordingOptions,
@@ -358,7 +353,14 @@ export class ReplayContainer implements ReplayContainerInterface {
358353
...(this.recordingMode === 'buffer' && { checkoutEveryNms: BUFFER_CHECKOUT_TIME }),
359354
emit: getHandleRecordingEmit(this),
360355
onMutation: this._onMutationHandler,
361-
...canvas,
356+
...(canvasOptions
357+
? {
358+
recordCanvas: canvasOptions.recordCanvas,
359+
getCanvasManager: canvasOptions.getCanvasManager,
360+
sampling: canvasOptions.sampling,
361+
dataURLOptions: canvasOptions.dataURLOptions,
362+
}
363+
: {}),
362364
});
363365
} catch (err) {
364366
this._handleException(err);
@@ -723,13 +725,6 @@ export class ReplayContainer implements ReplayContainerInterface {
723725
return spanToJSON(lastTransaction).description;
724726
}
725727

726-
/**
727-
* Internal integration use only, should not be public
728-
*/
729-
public addIntegration(name: string, options: Record<string, unknown>): void {
730-
this._integrations[name] = options;
731-
}
732-
733728
/**
734729
* Initialize and start all listeners to varying events (DOM,
735730
* Performance Observer, Recording, Sentry SDK, etc)

packages/replay/src/types/replay.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type { SKIPPED, THROTTLED } from '../util/throttle';
1414
import type { AllPerformanceEntry, AllPerformanceEntryData, ReplayPerformanceEntry } from './performance';
1515
import type { ReplayFrameEvent } from './replayFrame';
1616
import type { ReplayNetworkRequestOrResponse } from './request';
17-
import type { ReplayEventWithTime, RrwebRecordOptions } from './rrweb';
17+
import type { CanvasManagerInterface, CanvasManagerOptions, ReplayEventWithTime, RrwebRecordOptions } from './rrweb';
1818

1919
export type RecordingEvent = ReplayFrameEvent | ReplayEventWithTime;
2020
export type RecordingOptions = RrwebRecordOptions;
@@ -502,7 +502,6 @@ export interface ReplayContainer {
502502
updateUserActivity(): void;
503503
addUpdate(cb: AddUpdateCallback): void;
504504
getOptions(): ReplayPluginOptions;
505-
getIntegrations(): Record<string, Record<string, unknown>>;
506505
getSessionId(): string | undefined;
507506
checkAndHandleExpiredSession(): boolean | void;
508507
setInitialState(): void;
@@ -536,3 +535,15 @@ export interface SlowClickConfig {
536535
scrollTimeout: number;
537536
ignoreSelector: string;
538537
}
538+
539+
export interface ReplayCanvasIntegrationOptions {
540+
recordCanvas: true;
541+
getCanvasManager: (options: CanvasManagerOptions) => CanvasManagerInterface;
542+
sampling: {
543+
canvas: number;
544+
};
545+
dataURLOptions: {
546+
type: string;
547+
quality: number;
548+
};
549+
}

packages/replay/src/types/rrweb.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export interface CanvasManagerInterface {
5353
unlock(): void;
5454
}
5555

56-
export interface GetCanvasManagerOptions {
56+
export interface CanvasManagerOptions {
5757
recordCanvas: boolean;
5858
blockClass: string | RegExp;
5959
blockSelector: string | null;

0 commit comments

Comments
 (0)