Skip to content

Commit 48156d8

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

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';
@@ -906,7 +908,7 @@ export class ReplayContainer implements ReplayContainerInterface {
906908
*/
907909
async sendReplayRequest({
908910
events,
909-
replayId: event_id,
911+
replayId,
910912
segmentId: segment_id,
911913
includeReplayStartTimestamp,
912914
eventContext,
@@ -922,77 +924,40 @@ export class ReplayContainer implements ReplayContainerInterface {
922924

923925
const currentTimestamp = new Date().getTime();
924926

925-
const sdkInfo = {
926-
name: 'sentry.javascript.integration.replay',
927-
version: __SENTRY_REPLAY_VERSION__,
928-
};
927+
const hub = getCurrentHub();
928+
const client = hub.getClient();
929+
const scope = hub.getScope();
930+
const transport = client?.getTransport();
929931

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

956-
preparedEvent.sdk = {
957-
...preparedEvent.sdk,
958-
...sdkInfo,
959-
};
936+
const baseEvent: Event = {
937+
// @ts-ignore private api
938+
type: REPLAY_EVENT_NAME,
939+
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
940+
timestamp: currentTimestamp / 1000,
941+
error_ids: errorIds,
942+
trace_ids: traceIds,
943+
urls,
944+
replay_id: replayId,
945+
segment_id,
946+
};
960947

961-
preparedEvent.tags = {
962-
...preparedEvent.tags,
963-
sessionSampleRate: this._options.sessionSampleRate,
964-
errorSampleRate: this._options.errorSampleRate,
965-
replayType: this.session?.sampled,
966-
};
948+
const replayEvent = await getReplayEvent({ scope, client, replayId, event: baseEvent });
967949

968-
resolve(preparedEvent);
969-
});
970-
});
950+
replayEvent.tags = {
951+
...replayEvent.tags,
952+
sessionSampleRate: this._options.sessionSampleRate,
953+
errorSampleRate: this._options.errorSampleRate,
954+
replayType: this.session?.sampled,
955+
};
971956

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

993-
const client = getCurrentHub().getClient();
994959
try {
995-
return client?.getTransport()?.send(envelope);
960+
return transport.send(envelope);
996961
} catch {
997962
throw new Error(UNABLE_TO_SEND_REPLAY);
998963
}
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)