-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
ref(replay): refactor replayerStepper to be called less
#74540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7782d24
e31f109
ec15b19
f3154c6
af73b5a
873e5c9
38867b2
70c9054
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,62 +1,14 @@ | ||
| import type {Mirror} from '@sentry-internal/rrweb-snapshot'; | ||
|
|
||
| import replayerStepper from 'sentry/utils/replays/replayerStepper'; | ||
| import { | ||
| getNodeId, | ||
| type RecordingFrame, | ||
| type ReplayFrame, | ||
| } from 'sentry/utils/replays/types'; | ||
| import type {ReplayFrame} from 'sentry/utils/replays/types'; | ||
|
|
||
| export type Extraction = { | ||
| frame: ReplayFrame; | ||
| html: string | null; | ||
| timestamp: number; | ||
| }; | ||
|
|
||
| type Args = { | ||
| /** | ||
| * Frames where we should stop and extract html for a given dom node | ||
| */ | ||
| frames: ReplayFrame[] | undefined; | ||
|
|
||
| /** | ||
| * The rrweb events that constitute the replay | ||
| */ | ||
| rrwebEvents: RecordingFrame[] | undefined; | ||
|
|
||
| /** | ||
| * The replay start time, in ms | ||
| */ | ||
| startTimestampMs: number; | ||
| }; | ||
|
|
||
| export default function extractDomNodes({ | ||
| frames, | ||
| rrwebEvents, | ||
| startTimestampMs, | ||
| }: Args): Promise<Map<ReplayFrame, Extraction>> { | ||
| return replayerStepper({ | ||
| frames, | ||
| rrwebEvents, | ||
| startTimestampMs, | ||
| shouldVisitFrame: frame => { | ||
| const nodeId = getNodeId(frame); | ||
| return nodeId !== undefined && nodeId !== -1; | ||
| }, | ||
| onVisitFrame: (frame, collection, replayer) => { | ||
| const mirror = replayer.getMirror(); | ||
| const nodeId = getNodeId(frame); | ||
| const html = extractHtml(nodeId as number, mirror); | ||
| collection.set(frame as ReplayFrame, { | ||
| frame, | ||
| html, | ||
| timestamp: frame.timestampMs, | ||
| }); | ||
| }, | ||
| }); | ||
| } | ||
|
Comment on lines
-33
to
-57
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to |
||
|
|
||
| function extractHtml(nodeId: number, mirror: Mirror): string | null { | ||
| export default function extractHtml(nodeId: number, mirror: Mirror): string | null { | ||
| const node = mirror.getNode(nodeId); | ||
|
|
||
| const html = | ||
|
|
||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import {useQuery} from 'sentry/utils/queryClient'; | ||
| import type ReplayReader from 'sentry/utils/replays/replayReader'; | ||
|
|
||
| export type DomNodeChartDatapoint = { | ||
| added: number; | ||
| count: number; | ||
| endTimestampMs: number; | ||
| removed: number; | ||
| startTimestampMs: number; | ||
| timestampMs: number; | ||
| }; | ||
|
|
||
| export default function useCountDomNodes({replay}: {replay: null | ReplayReader}) { | ||
| return useQuery( | ||
| ['countDomNodes', replay], | ||
| () => { | ||
| return replay?.getCountDomNodes(); | ||
| }, | ||
| {enabled: Boolean(replay), cacheTime: Infinity} | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import {useQuery} from 'sentry/utils/queryClient'; | ||
| import type ReplayReader from 'sentry/utils/replays/replayReader'; | ||
|
|
||
| export default function useExtractDomNodes({replay}: {replay: null | ReplayReader}) { | ||
| return useQuery( | ||
| ['getDomNodes', replay], | ||
| () => { | ||
| return replay?.getExtractDomNodes(); | ||
| }, | ||
| {enabled: Boolean(replay), cacheTime: Infinity} | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import {useQuery} from 'sentry/utils/queryClient'; | ||
| import replayerStepper from 'sentry/utils/replays/replayerStepper'; | ||
| import type ReplayReader from 'sentry/utils/replays/replayReader'; | ||
| import type {RecordingFrame, ReplayFrame} from 'sentry/utils/replays/types'; | ||
|
|
||
| type Args = { | ||
| /** | ||
| * Offsets where we should stop and take a snapshot of the rendered HTML | ||
| */ | ||
| offsetMsToStopAt: number[]; | ||
|
|
||
| /** | ||
| * The rrweb events that constitute the replay | ||
| */ | ||
| rrwebEvents: RecordingFrame[] | undefined; | ||
|
|
||
| /** | ||
| * The replay startTimestampMs | ||
| */ | ||
| startTimestampMs: number; | ||
| }; | ||
|
|
||
| async function extractPageHtml({ | ||
| offsetMsToStopAt, | ||
| rrwebEvents, | ||
| startTimestampMs, | ||
| }: Args): Promise<[number, string][]> { | ||
| const frames: ReplayFrame[] = offsetMsToStopAt.map(offsetMs => ({ | ||
| offsetMs, | ||
| timestamp: new Date(startTimestampMs + offsetMs), | ||
| timestampMs: startTimestampMs + offsetMs, | ||
| })) as ReplayFrame[]; // TODO Don't smash types into `as ReplayFrame[]`, instead make the object really conform | ||
| const results = await replayerStepper<ReplayFrame, string>({ | ||
| frames, | ||
| rrwebEvents, | ||
| startTimestampMs, | ||
| visitFrameCallbacks: { | ||
| extractPageHtml: { | ||
| shouldVisitFrame: () => { | ||
| // Visit all the timestamps (converted to frames) that were passed in above | ||
| return true; | ||
| }, | ||
| onVisitFrame: (frame, collection, replayer) => { | ||
| const doc = replayer.getMirror().getNode(1); | ||
| const html = (doc as Document)?.body.outerHTML ?? ''; | ||
| collection.set(frame, html); | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
| return Array.from(results.extractPageHtml.entries()).map(([frame, html]) => { | ||
| return [frame.offsetMs, html]; | ||
| }); | ||
| } | ||
|
|
||
| interface Props { | ||
| offsetMsToStopAt: number[]; | ||
| replay: ReplayReader | null; | ||
| } | ||
|
|
||
| export default function useExtractedPageHtml({replay, offsetMsToStopAt}: Props) { | ||
| return useQuery( | ||
| ['extactPageHtml', replay, offsetMsToStopAt], | ||
| () => | ||
| extractPageHtml({ | ||
| offsetMsToStopAt, | ||
| rrwebEvents: replay?.getRRWebFrames(), | ||
| startTimestampMs: replay?.getReplay().started_at.getTime() ?? 0, | ||
| }), | ||
| {enabled: Boolean(replay), cacheTime: Infinity} | ||
| ); | ||
| } |
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to |
This file was deleted.
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to
replayReader.tsx