Skip to content

Commit

Permalink
feat(types): Upstream some replay types (#6506)
Browse files Browse the repository at this point in the history
  • Loading branch information
mydea authored Jan 3, 2023
1 parent b16ea89 commit a23bda5
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 32 deletions.
4 changes: 2 additions & 2 deletions packages/replay/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { getCurrentHub } from '@sentry/core';
import { Transport } from '@sentry/types';
import { ReplayRecordingData,Transport } from '@sentry/types';

import type { ReplayContainer, Session } from './src/types';

Expand Down Expand Up @@ -55,7 +55,7 @@ type SentReplayExpected = {
replayEventPayload?: ReplayEventPayload;
recordingHeader?: RecordingHeader;
recordingPayloadHeader?: RecordingPayloadHeader;
events?: string | Uint8Array;
events?: ReplayRecordingData;
};

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
Expand Down
5 changes: 3 additions & 2 deletions packages/replay/src/eventBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// TODO: figure out member access types and remove the line above

import { captureException } from '@sentry/core';
import { ReplayRecordingData } from '@sentry/types';
import { logger } from '@sentry/utils';

import type { EventBuffer, RecordingEvent, WorkerRequest, WorkerResponse } from './types';
Expand Down Expand Up @@ -95,7 +96,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
return this._eventBufferItemLength;
}

public async addEvent(event: RecordingEvent, isCheckout?: boolean): Promise<string | Uint8Array> {
public async addEvent(event: RecordingEvent, isCheckout?: boolean): Promise<ReplayRecordingData> {
if (isCheckout) {
// This event is a checkout, make sure worker buffer is cleared before
// proceeding.
Expand Down Expand Up @@ -159,7 +160,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
});
}

private _sendEventToWorker(event: RecordingEvent): Promise<string | Uint8Array> {
private _sendEventToWorker(event: RecordingEvent): Promise<ReplayRecordingData> {
const promise = this._postMessage({
id: this._getAndIncrementId(),
method: 'addEvent',
Expand Down
4 changes: 2 additions & 2 deletions packages/replay/src/replay.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable max-lines */ // TODO: We might want to split this file up
import { addGlobalEventProcessor, captureException, getCurrentHub, setContext } from '@sentry/core';
import { Breadcrumb, Event } from '@sentry/types';
import { Breadcrumb, ReplayEvent } from '@sentry/types';
import { addInstrumentationHandler, logger } from '@sentry/utils';
import debounce from 'lodash.debounce';
import { EventType, record } from 'rrweb';
Expand Down Expand Up @@ -927,7 +927,7 @@ export class ReplayContainer implements ReplayContainerInterface {
return;
}

const baseEvent: Event = {
const baseEvent: ReplayEvent = {
// @ts-ignore private api
type: REPLAY_EVENT_NAME,
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
Expand Down
6 changes: 4 additions & 2 deletions packages/replay/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ReplayRecordingData } from '@sentry/types';

import type { eventWithTime, recordOptions } from './types/rrweb';

export type RecordingEvent = eventWithTime;
Expand Down Expand Up @@ -47,7 +49,7 @@ export interface WorkerResponse {
id: number;
method: string;
success: boolean;
response: string | Uint8Array;
response: ReplayRecordingData;
}

export interface SampleRates {
Expand Down Expand Up @@ -211,7 +213,7 @@ export interface EventBuffer {
readonly length: number;
destroy(): void;
addEvent(event: RecordingEvent, isCheckout?: boolean): void;
finish(): Promise<string | Uint8Array>;
finish(): Promise<ReplayRecordingData>;
}

export type AddUpdateCallback = () => boolean | void;
Expand Down
4 changes: 3 additions & 1 deletion packages/replay/src/util/createPayload.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ReplayRecordingData } from '@sentry/types';

import type { RecordedEvents } from '../types';

export function createPayload({
Expand All @@ -6,7 +8,7 @@ export function createPayload({
}: {
events: RecordedEvents;
headers: Record<string, unknown>;
}): string | Uint8Array {
}): ReplayRecordingData {
let payloadWithSequence;

// XXX: newline is needed to separate sequence id from events
Expand Down
17 changes: 7 additions & 10 deletions packages/replay/src/util/createReplayEnvelope.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import { DsnComponents, Envelope, Event } from '@sentry/types';
import { DsnComponents, ReplayEnvelope, ReplayEvent, ReplayRecordingData } from '@sentry/types';
import { createEnvelope, createEventEnvelopeHeaders, getSdkMetadataForEnvelopeHeader } from '@sentry/utils';

export function createReplayEnvelope(
replayEvent: Event,
payloadWithSequence: string | Uint8Array,
replayEvent: ReplayEvent,
recordingData: ReplayRecordingData,
dsn: DsnComponents,
tunnel?: string,
): Envelope {
return createEnvelope(
): ReplayEnvelope {
return createEnvelope<ReplayEnvelope>(
createEventEnvelopeHeaders(replayEvent, getSdkMetadataForEnvelopeHeader(replayEvent), tunnel, dsn),
[
// @ts-ignore New types
[{ type: 'replay_event' }, replayEvent],
[
{
// @ts-ignore setting envelope
type: 'replay_recording',
length: payloadWithSequence.length,
length: recordingData.length,
},
// @ts-ignore: Type 'string' is not assignable to type 'ClientReport'.ts(2322)
payloadWithSequence,
recordingData,
],
],
);
Expand Down
8 changes: 4 additions & 4 deletions packages/replay/src/util/getReplayEvent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Scope } from '@sentry/core';
import { Client, Event } from '@sentry/types';
import { Client, ReplayEvent } from '@sentry/types';

export async function getReplayEvent({
client,
Expand All @@ -10,11 +10,11 @@ export async function getReplayEvent({
client: Client;
scope: Scope;
replayId: string;
event: Event;
}): Promise<Event | null> {
event: ReplayEvent;
}): Promise<ReplayEvent | null> {
// XXX: This event does not trigger `beforeSend` in SDK
// @ts-ignore private api
const preparedEvent: Event | null = await client._prepareEvent(event, { event_id }, scope);
const preparedEvent: ReplayEvent | null = await client._prepareEvent(event, { event_id }, scope);

if (preparedEvent) {
// extract the SDK name because `client._prepareEvent` doesn't add it to the event
Expand Down
9 changes: 5 additions & 4 deletions packages/replay/test/unit/util/createReplayEnvelope.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Event } from '@sentry/types';
import { ReplayEvent } from '@sentry/types';
import { makeDsn } from '@sentry/utils';

import { createReplayEnvelope } from '../../../src/util/createReplayEnvelope';

describe('createReplayEnvelope', () => {
const REPLAY_ID = 'MY_REPLAY_ID';

const replayEvent = {
const replayEvent: ReplayEvent = {
// @ts-ignore private api
type: 'replay_event',
timestamp: 1670837008.634,
error_ids: ['errorId'],
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('createReplayEnvelope', () => {
});

it('creates an envelope for a given Replay event', () => {
const envelope = createReplayEnvelope(replayEvent as Event, payloadWithSequence, dsn);
const envelope = createReplayEnvelope(replayEvent, payloadWithSequence, dsn);

expect(envelope).toEqual([
{
Expand Down Expand Up @@ -73,7 +74,7 @@ describe('createReplayEnvelope', () => {
});

it('creates an envelope with the `dsn` key in the header if `tunnel` is specified', () => {
const envelope = createReplayEnvelope(replayEvent as Event, payloadWithSequence, dsn, '/my-tunnel-endpoint');
const envelope = createReplayEnvelope(replayEvent, payloadWithSequence, dsn, '/my-tunnel-endpoint');

expect(envelope).toEqual([
{
Expand Down
5 changes: 3 additions & 2 deletions packages/replay/test/unit/util/getReplayEvent.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BrowserClient } from '@sentry/browser';
import { getCurrentHub, Hub, Scope } from '@sentry/core';
import { Client, Event } from '@sentry/types';
import { Client, ReplayEvent } from '@sentry/types';

import { REPLAY_EVENT_NAME } from '../../../src/constants';
import { getReplayEvent } from '../../../src/util/getReplayEvent';
Expand All @@ -25,14 +25,15 @@ describe('getReplayEvent', () => {
expect(scope).toBeDefined();

const replayId = 'replay-ID';
const event: Event = {
const event: ReplayEvent = {
// @ts-ignore private api
type: REPLAY_EVENT_NAME,
timestamp: 1670837008.634,
error_ids: ['error-ID'],
trace_ids: ['trace-ID'],
urls: ['https://sentry.io/'],
replay_id: replayId,
event_id: replayId,
segment_id: 3,
};

Expand Down
5 changes: 4 additions & 1 deletion packages/types/src/datacategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ export type DataCategory =
// SDK internal event, like client_reports
| 'internal'
// Profile event type
| 'profile';
| 'profile'
// Replay event types
| 'replay_event'
| 'replay_recording';
13 changes: 11 additions & 2 deletions packages/types/src/envelope.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ClientReport } from './clientreport';
import { DsnComponents } from './dsn';
import { Event } from './event';
import { ReplayEvent, ReplayRecordingData } from './replay';
import { SdkInfo } from './sdkinfo';
import { Session, SessionAggregates } from './session';
import { Transaction } from './transaction';
Expand All @@ -27,7 +28,9 @@ export type EnvelopeItemType =
| 'transaction'
| 'attachment'
| 'event'
| 'profile';
| 'profile'
| 'replay_event'
| 'replay_recording';

export type BaseEnvelopeHeaders = {
[key: string]: unknown;
Expand Down Expand Up @@ -62,6 +65,8 @@ type UserFeedbackItemHeaders = { type: 'user_report' };
type SessionItemHeaders = { type: 'session' };
type SessionAggregatesItemHeaders = { type: 'sessions' };
type ClientReportItemHeaders = { type: 'client_report' };
type ReplayEventItemHeaders = { type: 'replay_event' };
type ReplayRecordingItemHeaders = { type: 'replay_recording'; length: number };

export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event>;
export type AttachmentItem = BaseEnvelopeItem<AttachmentItemHeaders, string | Uint8Array>;
Expand All @@ -70,14 +75,18 @@ export type SessionItem =
| BaseEnvelopeItem<SessionItemHeaders, Session>
| BaseEnvelopeItem<SessionAggregatesItemHeaders, SessionAggregates>;
export type ClientReportItem = BaseEnvelopeItem<ClientReportItemHeaders, ClientReport>;
type ReplayEventItem = BaseEnvelopeItem<ReplayEventItemHeaders, ReplayEvent>;
type ReplayRecordingItem = BaseEnvelopeItem<ReplayRecordingItemHeaders, ReplayRecordingData>;

export type EventEnvelopeHeaders = { event_id: string; sent_at: string; trace?: DynamicSamplingContext };
type SessionEnvelopeHeaders = { sent_at: string };
type ClientReportEnvelopeHeaders = BaseEnvelopeHeaders;
type ReplayEnvelopeHeaders = BaseEnvelopeHeaders;

export type EventEnvelope = BaseEnvelope<EventEnvelopeHeaders, EventItem | AttachmentItem | UserFeedbackItem>;
export type SessionEnvelope = BaseEnvelope<SessionEnvelopeHeaders, SessionItem>;
export type ClientReportEnvelope = BaseEnvelope<ClientReportEnvelopeHeaders, ClientReportItem>;
export type ReplayEnvelope = [ReplayEnvelopeHeaders, [ReplayEventItem, ReplayRecordingItem]];

export type Envelope = EventEnvelope | SessionEnvelope | ClientReportEnvelope;
export type Envelope = EventEnvelope | SessionEnvelope | ClientReportEnvelope | ReplayEnvelope;
export type EnvelopeItem = Envelope[1][number];
2 changes: 2 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type {
EventEnvelope,
EventEnvelopeHeaders,
EventItem,
ReplayEnvelope,
SessionEnvelope,
SessionItem,
UserFeedbackItem,
Expand All @@ -39,6 +40,7 @@ export type { ExtractedNodeRequestData, HttpHeaderValue, Primitive, WorkerLocati
export type { ClientOptions, Options } from './options';
export type { Package } from './package';
export type { PolymorphicEvent, PolymorphicRequest } from './polymorphics';
export type { ReplayEvent, ReplayRecordingData } from './replay';
export type { QueryParams, Request } from './request';
export type { Runtime } from './runtime';
export type { CaptureContext, Scope, ScopeContext } from './scope';
Expand Down
19 changes: 19 additions & 0 deletions packages/types/src/replay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Event } from './event';

/**
* NOTE: These types are still considered Beta and subject to change.
* @hidden
*/
export interface ReplayEvent extends Event {
urls: string[];
error_ids: string[];
trace_ids: string[];
replay_id: string;
segment_id: number;
}

/**
* NOTE: These types are still considered Beta and subject to change.
* @hidden
*/
export type ReplayRecordingData = string | Uint8Array;
2 changes: 2 additions & 0 deletions packages/utils/src/envelope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP: Record<EnvelopeItemType, DataCategory> = {
client_report: 'internal',
user_report: 'default',
profile: 'profile',
replay_event: 'replay_event',
replay_recording: 'replay_recording',
};

/**
Expand Down

0 comments on commit a23bda5

Please sign in to comment.