Skip to content

Commit

Permalink
run replay in afterAllSetup
Browse files Browse the repository at this point in the history
  • Loading branch information
mydea committed Jul 1, 2024
1 parent acef6e5 commit eeae961
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 48 deletions.
41 changes: 13 additions & 28 deletions packages/replay-internal/src/integration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getClient, parseSampleRate } from '@sentry/core';
import type { BrowserClientReplayOptions, Integration, IntegrationFn } from '@sentry/types';
import { parseSampleRate } from '@sentry/core';
import type { BrowserClientReplayOptions, Client, Integration, IntegrationFn } from '@sentry/types';
import { consoleSandbox, dropUndefinedKeys, isBrowser } from '@sentry/utils';

import {
Expand Down Expand Up @@ -215,13 +215,13 @@ export class Replay implements Integration {
/**
* Setup and initialize replay container
*/
public setupOnce(): void {
if (!isBrowser()) {
public afterAllSetup(client: Client): void {
if (!isBrowser() || this._replay) {
return;
}

this._setup();
this._initialize();
this._setup(client);
this._initialize(client);
}

/**
Expand Down Expand Up @@ -292,24 +292,19 @@ export class Replay implements Integration {
/**
* Initializes replay.
*/
protected _initialize(): void {
protected _initialize(client: Client): void {
if (!this._replay) {
return;
}

// We have to run this in _initialize, because this runs in setTimeout
// So when this runs all integrations have been added
// Before this, we cannot access integrations on the client,
// so we need to mutate the options here
this._maybeLoadFromReplayCanvasIntegration();

this._maybeLoadFromReplayCanvasIntegration(client);
this._replay.initializeSampling();
}

/** Setup the integration. */
private _setup(): void {
private _setup(client: Client): void {
// Client is not available in constructor, so we need to wait until setupOnce
const finalOptions = loadReplayOptionsFromClient(this._initialOptions);
const finalOptions = loadReplayOptionsFromClient(this._initialOptions, client);

this._replay = new ReplayContainer({
options: finalOptions,
Expand All @@ -318,12 +313,11 @@ export class Replay implements Integration {
}

/** Get canvas options from ReplayCanvas integration, if it is also added. */
private _maybeLoadFromReplayCanvasIntegration(): void {
private _maybeLoadFromReplayCanvasIntegration(client: Client): void {
// To save bundle size, we skip checking for stuff here
// and instead just try-catch everything - as generally this should all be defined
/* eslint-disable @typescript-eslint/no-non-null-assertion */
try {
const client = getClient()!;
const canvasIntegration = client.getIntegrationByName('ReplayCanvas') as Integration & {
getOptions(): ReplayCanvasIntegrationOptions;
};
Expand All @@ -340,24 +334,15 @@ export class Replay implements Integration {
}

/** Parse Replay-related options from SDK options */
function loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions): ReplayPluginOptions {
const client = getClient();
const opt = client && (client.getOptions() as BrowserClientReplayOptions);
function loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions, client: Client): ReplayPluginOptions {
const opt = client.getOptions() as BrowserClientReplayOptions;

const finalOptions: ReplayPluginOptions = {
sessionSampleRate: 0,
errorSampleRate: 0,
...dropUndefinedKeys(initialOptions),
};

if (!opt) {
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.warn('SDK client is not available.');
});
return finalOptions;
}

const replaysSessionSampleRate = parseSampleRate(opt.replaysSessionSampleRate);
const replaysOnErrorSampleRate = parseSampleRate(opt.replaysOnErrorSampleRate);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getClient } from '@sentry/core';
import type { Event } from '@sentry/types';

import { REPLAY_EVENT_NAME, SESSION_IDLE_EXPIRE_DURATION } from '../../../src/constants';
Expand Down Expand Up @@ -133,8 +134,8 @@ describe('Integration | coreHandlers | handleGlobalEvent', () => {

it('tags errors and transactions with replay id for session samples', async () => {
const { replay, integration } = await resetSdkMock({});
// @ts-expect-error protected but ok to use for testing
integration._initialize();
integration['_initialize'](getClient()!);

const transaction = Transaction();
const error = Error();
expect(handleGlobalEventListener(replay)(transaction, {})).toEqual(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ describe('Integration | errorSampleRate', () => {
},
autoStart: false,
});
integration['_initialize']();
integration['_initialize'](getClient()!);

expect(replay.recordingMode).toBe('session');
const sessionId = replay.getSessionId();
Expand Down Expand Up @@ -899,7 +899,7 @@ describe('Integration | errorSampleRate', () => {
},
autoStart: false,
});
integration['_initialize']();
integration['_initialize'](getClient()!);

vi.runAllTimers();

Expand Down Expand Up @@ -943,7 +943,7 @@ describe('Integration | errorSampleRate', () => {
},
autoStart: false,
});
integration['_initialize']();
integration['_initialize'](getClient()!);
const optionsEvent = createOptionsEvent(replay);

const TEST_EVENT = getTestEventIncremental({ timestamp: BASE_TIMESTAMP });
Expand Down
4 changes: 2 additions & 2 deletions packages/replay-internal/test/integration/sampling.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getClient } from '@sentry/core';
import { resetSdkMock } from '../mocks/resetSdkMock';
import { useFakeTimers } from '../utils/use-fake-timers';

Expand Down Expand Up @@ -57,8 +58,7 @@ describe('Integration | sampling', () => {
// @ts-expect-error private API
const spyAddListeners = vi.spyOn(replay, '_addListeners');

// @ts-expect-error protected
integration._initialize();
integration['_initialize'](getClient()!);

vi.runAllTimers();

Expand Down
18 changes: 7 additions & 11 deletions packages/replay-internal/test/mocks/mockSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,8 @@ export async function mockSdk({ replayOptions, sentryOptions, autoStart = true }
_initialized = value;
}

public setupOnce(): void {
// do nothing
}

public initialize(): void {
return super._initialize();
public afterAllSetup(): void {
// do nothing, we need to manually initialize this
}
}

Expand All @@ -76,7 +72,7 @@ export async function mockSdk({ replayOptions, sentryOptions, autoStart = true }
...replayOptions,
});

init({
const client = init({
...getDefaultClientOptions(),
dsn: 'https://dsn@ingest.f00.f00/1',
autoSessionTracking: false,
Expand All @@ -86,14 +82,14 @@ export async function mockSdk({ replayOptions, sentryOptions, autoStart = true }
replaysOnErrorSampleRate: 0.0,
...sentryOptions,
integrations: [replayIntegration],
});
})!;

// Instead of `setupOnce`, which is tricky to test, we call this manually here
replayIntegration['_setup']();
// Instead of `afterAllSetup`, which is tricky to test, we call this manually here
replayIntegration['_setup'](client);

if (autoStart) {
// Only exists in our mock
replayIntegration.initialize();
replayIntegration['_initialize'](client);
}

const replay = replayIntegration['_replay']!;
Expand Down
5 changes: 3 additions & 2 deletions packages/replay-internal/test/utils/TestClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseClient, createTransport, initAndBind } from '@sentry/core';
import type {
BrowserClientReplayOptions,
Client,
ClientOptions,
Event,
ParameterizedString,
Expand Down Expand Up @@ -33,8 +34,8 @@ export class TestClient extends BaseClient<TestClientOptions> {
}
}

export function init(options: TestClientOptions): void {
initAndBind(TestClient, options);
export function init(options: TestClientOptions): Client {
return initAndBind(TestClient, options);
}

export function getDefaultClientOptions(options: Partial<TestClientOptions> = {}): ClientOptions {
Expand Down

0 comments on commit eeae961

Please sign in to comment.