123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import {Replayer} from '@sentry-internal/rrweb';
- import type {RecordingFrame} from 'sentry/utils/replays/types';
- export type DomNodeChartDatapoint = {
- count: number;
- endTimestampMs: number;
- startTimestampMs: number;
- timestampMs: number;
- };
- type Args = {
- frames: RecordingFrame[] | undefined;
- rrwebEvents: RecordingFrame[] | undefined;
- startTimestampMs: number;
- };
- export default function countDomNodes({
- frames = [],
- rrwebEvents,
- startTimestampMs,
- }: Args): Promise<DomNodeChartDatapoint[]> {
- return new Promise(resolve => {
- const datapoints = new Map<RecordingFrame, DomNodeChartDatapoint>();
- const player = createPlayer(rrwebEvents);
- const nextFrame = (function () {
- let i = 0;
- const len = frames.length;
- // how many frames we look at depends on the number of total frames
- return () => frames[(i += Math.max(Math.round(len * 0.007), 1))];
- })();
- const onDone = () => {
- resolve(Array.from(datapoints.values()));
- };
- const nextOrDone = () => {
- const next = nextFrame();
- if (next) {
- matchFrame(next);
- } else {
- onDone();
- }
- };
- type FrameRef = {
- frame: undefined | RecordingFrame;
- };
- const nodeIdRef: FrameRef = {
- frame: undefined,
- };
- const handlePause = () => {
- const frame = nodeIdRef.frame as RecordingFrame;
- const idCount = player.getMirror().getIds().length; // gets number of DOM nodes present
- datapoints.set(frame as RecordingFrame, {
- count: idCount,
- timestampMs: frame.timestamp,
- startTimestampMs: frame.timestamp,
- endTimestampMs: frame.timestamp,
- });
- nextOrDone();
- };
- const matchFrame = frame => {
- if (!frame) {
- nextOrDone();
- return;
- }
- nodeIdRef.frame = frame;
- window.setTimeout(() => {
- player.pause(frame.timestamp - startTimestampMs);
- }, 0);
- };
- player.on('pause', handlePause);
- matchFrame(nextFrame());
- });
- }
- function createPlayer(rrwebEvents): Replayer {
- const domRoot = document.createElement('div');
- domRoot.className = 'sentry-block';
- const {style} = domRoot;
- style.position = 'fixed';
- style.inset = '0';
- style.width = '0';
- style.height = '0';
- style.overflow = 'hidden';
- document.body.appendChild(domRoot);
- const replayerRef = new Replayer(rrwebEvents, {
- root: domRoot,
- loadTimeout: 1,
- showWarning: false,
- blockClass: 'sentry-block',
- speed: 99999,
- skipInactive: true,
- triggerFocus: false,
- mouseTail: false,
- });
- return replayerRef;
- }
|