Skip to content

Commit fc9b6d8

Browse files
committed
ref(replay): Avoid using private hub._withClient
This is brittle, and can actually be refactored quite easily.
1 parent 8ae1ce4 commit fc9b6d8

File tree

4 files changed

+102
-68
lines changed

4 files changed

+102
-68
lines changed

packages/replay/src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ export const MAX_SESSION_LIFE = 1_800_000; // 30 minutes
2525
*/
2626
export const DEFAULT_SESSION_SAMPLE_RATE = 0.1;
2727
export const DEFAULT_ERROR_SAMPLE_RATE = 1.0;
28+
29+
export const REPLAY_SDK_INFO = {
30+
name: 'sentry.javascript.integration.replay',
31+
version: __SENTRY_REPLAY_VERSION__,
32+
};

packages/replay/src/replay.ts

Lines changed: 33 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable max-lines */ // TODO: We might want to split this file up
2-
import { addGlobalEventProcessor, captureException, getCurrentHub, Scope, setContext } from '@sentry/core';
3-
import { Breadcrumb, Client, Event } from '@sentry/types';
4-
import { addInstrumentationHandler, createEnvelope, logger } from '@sentry/utils';
2+
import { addGlobalEventProcessor, captureException, getCurrentHub, setContext } from '@sentry/core';
3+
import { Breadcrumb, Event } from '@sentry/types';
4+
import { addInstrumentationHandler, logger } from '@sentry/utils';
55
import debounce from 'lodash.debounce';
66
import { EventType, record } from 'rrweb';
77

@@ -44,6 +44,8 @@ import { addMemoryEntry } from './util/addMemoryEntry';
4444
import { createBreadcrumb } from './util/createBreadcrumb';
4545
import { createPayload } from './util/createPayload';
4646
import { createPerformanceSpans } from './util/createPerformanceSpans';
47+
import { createReplayEnvelope } from './util/createReplayEnvelope';
48+
import { getReplayEvent } from './util/getReplayEvent';
4749
import { isExpired } from './util/isExpired';
4850
import { isSessionExpired } from './util/isSessionExpired';
4951
import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/monkeyPatchRecordDroppedEvent';
@@ -901,7 +903,7 @@ export class ReplayContainer implements ReplayContainerInterface {
901903
*/
902904
async sendReplayRequest({
903905
events,
904-
replayId: event_id,
906+
replayId,
905907
segmentId: segment_id,
906908
includeReplayStartTimestamp,
907909
eventContext,
@@ -917,77 +919,40 @@ export class ReplayContainer implements ReplayContainerInterface {
917919

918920
const currentTimestamp = new Date().getTime();
919921

920-
const sdkInfo = {
921-
name: 'sentry.javascript.integration.replay',
922-
version: __SENTRY_REPLAY_VERSION__,
923-
};
922+
const hub = getCurrentHub();
923+
const client = hub.getClient();
924+
const scope = hub.getScope();
925+
const transport = client?.getTransport();
924926

925-
const replayEvent = await new Promise(resolve => {
926-
getCurrentHub()
927-
// @ts-ignore private api
928-
?._withClient(async (client: Client, scope: Scope) => {
929-
// XXX: This event does not trigger `beforeSend` in SDK
930-
// @ts-ignore private api
931-
const preparedEvent: Event = await client._prepareEvent(
932-
{
933-
type: REPLAY_EVENT_NAME,
934-
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
935-
timestamp: currentTimestamp / 1000,
936-
error_ids: errorIds,
937-
trace_ids: traceIds,
938-
urls,
939-
replay_id: event_id,
940-
segment_id,
941-
},
942-
{ event_id },
943-
scope,
944-
);
945-
const session = scope && scope.getSession();
946-
if (session) {
947-
// @ts-ignore private api
948-
client._updateSessionFromEvent(session, preparedEvent);
949-
}
927+
if (!client || !scope || !transport) {
928+
return;
929+
}
950930

951-
preparedEvent.sdk = {
952-
...preparedEvent.sdk,
953-
...sdkInfo,
954-
};
931+
const baseEvent: Event = {
932+
// @ts-ignore private api
933+
type: REPLAY_EVENT_NAME,
934+
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
935+
timestamp: currentTimestamp / 1000,
936+
error_ids: errorIds,
937+
trace_ids: traceIds,
938+
urls,
939+
replay_id: replayId,
940+
segment_id,
941+
};
955942

956-
preparedEvent.tags = {
957-
...preparedEvent.tags,
958-
sessionSampleRate: this.options.sessionSampleRate,
959-
errorSampleRate: this.options.errorSampleRate,
960-
replayType: this.session?.sampled,
961-
};
943+
const replayEvent = await getReplayEvent({ scope, client, replayId, event: baseEvent });
962944

963-
resolve(preparedEvent);
964-
});
965-
});
945+
replayEvent.tags = {
946+
...replayEvent.tags,
947+
sessionSampleRate: this.options.sessionSampleRate,
948+
errorSampleRate: this.options.errorSampleRate,
949+
replayType: this.session?.sampled,
950+
};
966951

967-
const envelope = createEnvelope(
968-
{
969-
event_id,
970-
sent_at: new Date().toISOString(),
971-
sdk: sdkInfo,
972-
},
973-
[
974-
// @ts-ignore New types
975-
[{ type: 'replay_event' }, replayEvent],
976-
[
977-
{
978-
// @ts-ignore setting envelope
979-
type: 'replay_recording',
980-
length: payloadWithSequence.length,
981-
},
982-
// @ts-ignore: Type 'string' is not assignable to type 'ClientReport'.ts(2322)
983-
payloadWithSequence,
984-
],
985-
],
986-
);
952+
const envelope = createReplayEnvelope(replayId, replayEvent, payloadWithSequence);
987953

988-
const client = getCurrentHub().getClient();
989954
try {
990-
return client?.getTransport()?.send(envelope);
955+
return transport.send(envelope);
991956
} catch {
992957
throw new Error(UNABLE_TO_SEND_REPLAY);
993958
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Envelope, Event } from '@sentry/types';
2+
import { createEnvelope } from '@sentry/utils';
3+
4+
import { REPLAY_SDK_INFO } from '../constants';
5+
6+
export function createReplayEnvelope(
7+
replayId: string,
8+
replayEvent: Event,
9+
payloadWithSequence: string | Uint8Array,
10+
): Envelope {
11+
return createEnvelope(
12+
{
13+
event_id: replayId,
14+
sent_at: new Date().toISOString(),
15+
sdk: REPLAY_SDK_INFO,
16+
},
17+
[
18+
// @ts-ignore New types
19+
[{ type: 'replay_event' }, replayEvent],
20+
[
21+
{
22+
// @ts-ignore setting envelope
23+
type: 'replay_recording',
24+
length: payloadWithSequence.length,
25+
},
26+
// @ts-ignore: Type 'string' is not assignable to type 'ClientReport'.ts(2322)
27+
payloadWithSequence,
28+
],
29+
],
30+
);
31+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Scope } from '@sentry/core';
2+
import { Client, Event } from '@sentry/types';
3+
4+
import { REPLAY_SDK_INFO } from '../constants';
5+
6+
export async function getReplayEvent({
7+
client,
8+
scope,
9+
replayId: event_id,
10+
event,
11+
}: {
12+
client: Client;
13+
scope: Scope;
14+
replayId: string;
15+
event: Event;
16+
}): Promise<Event> {
17+
// XXX: This event does not trigger `beforeSend` in SDK
18+
// @ts-ignore private api
19+
const preparedEvent: Event = await client._prepareEvent(event, { event_id }, scope);
20+
21+
const session = scope && scope.getSession();
22+
if (session) {
23+
// @ts-ignore private api
24+
client._updateSessionFromEvent(session, preparedEvent);
25+
}
26+
27+
preparedEvent.sdk = {
28+
...preparedEvent.sdk,
29+
...REPLAY_SDK_INFO,
30+
};
31+
32+
return preparedEvent;
33+
}

0 commit comments

Comments
 (0)