Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
Comment on lines +190 to +191
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn we should have named these replay and recording to be consistent with our other event types

};

/**
Expand Down