diff --git a/packages/replay/src/index.ts b/packages/replay/src/index.ts index 239cd727d67f..3e6b01f39f5c 100644 --- a/packages/replay/src/index.ts +++ b/packages/replay/src/index.ts @@ -2,8 +2,13 @@ export { Replay } from './integration'; export type { BreadcrumbFrame, BreadcrumbFrameEvent, + OptionFrameEvent, ReplayFrame, ReplayFrameEvent, SpanFrame, SpanFrameEvent, -} from './types/replayFrame'; +} from './types'; +export { EventType } from '@sentry-internal/rrweb'; +export { NodeType } from '@sentry-internal/rrweb-snapshot'; +export type { eventWithTime, fullSnapshotEvent } from '@sentry-internal/rrweb'; +export type { serializedNodeWithId } from '@sentry-internal/rrweb-snapshot'; diff --git a/packages/replay/src/types/index.ts b/packages/replay/src/types/index.ts index 2461e4f3ac8e..0fc39c9cd411 100644 --- a/packages/replay/src/types/index.ts +++ b/packages/replay/src/types/index.ts @@ -1,4 +1,5 @@ export * from './performance'; export * from './replay'; export * from './replayFrame'; +export * from './request'; export * from './rrweb'; diff --git a/packages/replay/src/types/performance.ts b/packages/replay/src/types/performance.ts index 0ff647e7d7d0..49590a361cdb 100644 --- a/packages/replay/src/types/performance.ts +++ b/packages/replay/src/types/performance.ts @@ -1,3 +1,5 @@ +import type { ReplayNetworkRequestOrResponse } from './request'; + export type AllPerformanceEntry = PerformancePaintTiming | PerformanceResourceTiming | PerformanceNavigationTiming; // PerformancePaintTiming and PerformanceNavigationTiming are only available with TS 4.4 and newer @@ -124,6 +126,8 @@ export interface NetworkRequestData { statusCode?: number; requestBodySize?: number; responseBodySize?: number; + request?: ReplayNetworkRequestOrResponse; + response?: ReplayNetworkRequestOrResponse; } export interface HistoryData { diff --git a/packages/replay/src/types/replay.ts b/packages/replay/src/types/replay.ts index 262dcbf65a88..e1ddf9c9619e 100644 --- a/packages/replay/src/types/replay.ts +++ b/packages/replay/src/types/replay.ts @@ -11,6 +11,7 @@ import type { import type { SKIPPED, THROTTLED } from '../util/throttle'; import type { AllPerformanceEntry } from './performance'; import type { ReplayFrameEvent } from './replayFrame'; +import type { ReplayNetworkRequestOrResponse } from './request'; import type { eventWithTime, recordOptions } from './rrweb'; export type RecordingEvent = ReplayFrameEvent | eventWithTime; @@ -444,24 +445,6 @@ export type FetchHint = FetchBreadcrumbHint & { response: Response; }; -type JsonObject = Record; -type JsonArray = unknown[]; - -export type NetworkBody = JsonObject | JsonArray | string; - -export type NetworkMetaWarning = 'JSON_TRUNCATED' | 'TEXT_TRUNCATED' | 'INVALID_JSON' | 'URL_SKIPPED'; - -interface NetworkMeta { - warnings?: NetworkMetaWarning[]; -} - -export interface ReplayNetworkRequestOrResponse { - size?: number; - body?: NetworkBody; - headers: Record; - _meta?: NetworkMeta; -} - export type ReplayNetworkRequestData = { startTimestamp: number; endTimestamp: number; diff --git a/packages/replay/src/types/replayFrame.ts b/packages/replay/src/types/replayFrame.ts index 463e462851e6..529b1b428a6f 100644 --- a/packages/replay/src/types/replayFrame.ts +++ b/packages/replay/src/types/replayFrame.ts @@ -1,9 +1,17 @@ -import type { Breadcrumb, FetchBreadcrumbData, XhrBreadcrumbData } from '@sentry/types'; - -import type { AllEntryData } from './performance'; -import type { EventType } from './rrweb'; - -interface BaseReplayFrame { +import type { EventType } from '@sentry-internal/rrweb'; +import type { Breadcrumb } from '@sentry/types'; + +import type { + HistoryData, + LargestContentfulPaintData, + MemoryData, + NavigationData, + NetworkRequestData, + PaintData, + ResourceData, +} from './performance'; + +interface BaseBreadcrumbFrame { timestamp: number; /** * For compatibility reasons @@ -29,7 +37,7 @@ interface ConsoleFrameData { logger: string; arguments?: unknown[]; } -interface ConsoleFrame extends BaseReplayFrame { +interface ConsoleFrame extends BaseBreadcrumbFrame { category: 'console'; level: Breadcrumb['level']; message: string; @@ -37,35 +45,23 @@ interface ConsoleFrame extends BaseReplayFrame { } type ClickFrameData = BaseDomFrameData; -interface ClickFrame extends BaseReplayFrame { +interface ClickFrame extends BaseBreadcrumbFrame { category: 'ui.click'; message: string; data: ClickFrameData; } -interface FetchFrame extends BaseReplayFrame { - category: 'fetch'; - type: 'http'; - data: FetchBreadcrumbData; -} - -interface InputFrame extends BaseReplayFrame { +interface InputFrame extends BaseBreadcrumbFrame { category: 'ui.input'; message: string; } -interface XhrFrame extends BaseReplayFrame { - category: 'xhr'; - type: 'http'; - data: XhrBreadcrumbData; -} - /* Breadcrumbs from Replay */ interface MutationFrameData { count: number; limit: boolean; } -interface MutationFrame extends BaseReplayFrame { +interface MutationFrame extends BaseBreadcrumbFrame { category: 'replay.mutations'; data: MutationFrameData; } @@ -77,16 +73,16 @@ interface KeyboardEventFrameData extends BaseDomFrameData { altKey: boolean; key: string; } -interface KeyboardEventFrame extends BaseReplayFrame { +interface KeyboardEventFrame extends BaseBreadcrumbFrame { category: 'ui.keyDown'; data: KeyboardEventFrameData; } -interface BlurFrame extends BaseReplayFrame { +interface BlurFrame extends BaseBreadcrumbFrame { category: 'ui.blur'; } -interface FocusFrame extends BaseReplayFrame { +interface FocusFrame extends BaseBreadcrumbFrame { category: 'ui.focus'; } @@ -95,46 +91,89 @@ interface SlowClickFrameData extends ClickFrameData { timeAfterClickFs: number; endReason: string; } -interface SlowClickFrame extends BaseReplayFrame { +interface SlowClickFrame extends BaseBreadcrumbFrame { category: 'ui.slowClickDetected'; data: SlowClickFrameData; } interface OptionFrame { - sessionSampleRate: number; - errorSampleRate: number; - useCompressionOption: boolean; blockAllMedia: boolean; - maskAllText: boolean; + errorSampleRate: number; maskAllInputs: boolean; - useCompression: boolean; - networkDetailHasUrls: boolean; + maskAllText: boolean; networkCaptureBodies: boolean; + networkDetailHasUrls: boolean; networkRequestHasHeaders: boolean; networkResponseHasHeaders: boolean; + sessionSampleRate: number; + useCompression: boolean; + useCompressionOption: boolean; } export type BreadcrumbFrame = | ConsoleFrame | ClickFrame - | FetchFrame | InputFrame - | XhrFrame | KeyboardEventFrame | BlurFrame | FocusFrame | SlowClickFrame | MutationFrame - | BaseReplayFrame; + | BaseBreadcrumbFrame; -export interface SpanFrame { +interface BaseSpanFrame { op: string; description: string; startTimestamp: number; endTimestamp: number; - data: AllEntryData; + data?: undefined | Record; +} + +interface HistoryFrame extends BaseSpanFrame { + data: HistoryData; + op: 'navigation.push'; +} + +interface LargestContentfulPaintFrame extends BaseSpanFrame { + data: LargestContentfulPaintData; + op: 'largest-contentful-paint'; +} + +interface MemoryFrame extends BaseSpanFrame { + data: MemoryData; + op: 'memory'; +} + +interface NavigationFrame extends BaseSpanFrame { + data: NavigationData; + op: 'navigation.navigate' | 'navigation.reload' | 'navigation.back_forward'; +} + +interface PaintFrame extends BaseSpanFrame { + data: PaintData; + op: 'paint'; +} + +interface RequestFrame extends BaseSpanFrame { + data: NetworkRequestData; + op: 'resource.fetch' | 'resource.xhr'; +} + +interface ResourceFrame extends BaseSpanFrame { + data: ResourceData; + op: 'resource.css' | 'resource.iframe' | 'resource.img' | 'resource.link' | 'resource.other' | 'resource.script'; } +export type SpanFrame = + | BaseSpanFrame + | HistoryFrame + | RequestFrame + | LargestContentfulPaintFrame + | MemoryFrame + | NavigationFrame + | PaintFrame + | ResourceFrame; + export type ReplayFrame = BreadcrumbFrame | SpanFrame; interface RecordingCustomEvent { diff --git a/packages/replay/src/types/request.ts b/packages/replay/src/types/request.ts new file mode 100644 index 000000000000..ae24574d4b7e --- /dev/null +++ b/packages/replay/src/types/request.ts @@ -0,0 +1,17 @@ +type JsonObject = Record; +type JsonArray = unknown[]; + +export type NetworkBody = JsonObject | JsonArray | string; + +export type NetworkMetaWarning = 'JSON_TRUNCATED' | 'TEXT_TRUNCATED' | 'INVALID_JSON' | 'URL_SKIPPED'; + +interface NetworkMeta { + warnings?: NetworkMetaWarning[]; +} + +export interface ReplayNetworkRequestOrResponse { + size?: number; + body?: NetworkBody; + headers: Record; + _meta?: NetworkMeta; +} diff --git a/packages/replay/src/types/rrweb.ts b/packages/replay/src/types/rrweb.ts index 7f2dfec78110..cfbe4cddf4c3 100644 --- a/packages/replay/src/types/rrweb.ts +++ b/packages/replay/src/types/rrweb.ts @@ -1,18 +1,10 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import type { EventType } from '@sentry-internal/rrweb'; + type blockClass = string | RegExp; type maskTextClass = string | RegExp; -export enum EventType { - DomContentLoaded = 0, - Load = 1, - FullSnapshot = 2, - IncrementalSnapshot = 3, - Meta = 4, - Custom = 5, - Plugin = 6, -} - /** * This is a partial copy of rrweb's eventWithTime type which only contains the properties * we specifcally need in the SDK. diff --git a/packages/replay/src/util/addEvent.ts b/packages/replay/src/util/addEvent.ts index 2a5458887af6..16f653e9fc5d 100644 --- a/packages/replay/src/util/addEvent.ts +++ b/packages/replay/src/util/addEvent.ts @@ -1,8 +1,8 @@ +import { EventType } from '@sentry-internal/rrweb'; import { getCurrentHub } from '@sentry/core'; import { logger } from '@sentry/utils'; import type { AddEventResult, RecordingEvent, ReplayContainer, ReplayFrameEvent } from '../types'; -import { EventType } from '../types/rrweb'; import { timestampToMs } from './timestampToMs'; function isCustomEvent(event: RecordingEvent): event is ReplayFrameEvent { diff --git a/packages/replay/src/util/handleRecordingEmit.ts b/packages/replay/src/util/handleRecordingEmit.ts index ffb0a993dc89..cc7c87afed48 100644 --- a/packages/replay/src/util/handleRecordingEmit.ts +++ b/packages/replay/src/util/handleRecordingEmit.ts @@ -1,8 +1,8 @@ +import { EventType } from '@sentry-internal/rrweb'; import { logger } from '@sentry/utils'; import { saveSession } from '../session/saveSession'; import type { AddEventResult, OptionFrameEvent, RecordingEvent, ReplayContainer } from '../types'; -import { EventType } from '../types/rrweb'; import { addEvent } from './addEvent'; type RecordingEmitCallback = (event: RecordingEvent, isCheckout?: boolean) => void;