123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import {Fragment, useMemo} from 'react';
- import styled from '@emotion/styled';
- import EmptyMessage from 'sentry/components/emptyMessage';
- import Placeholder from 'sentry/components/placeholder';
- import {useReplayContext} from 'sentry/components/replays/replayContext';
- import {t} from 'sentry/locale';
- import {space} from 'sentry/styles/space';
- import {useQuery} from 'sentry/utils/queryClient';
- import countDomNodes from 'sentry/utils/replays/countDomNodes';
- import type ReplayReader from 'sentry/utils/replays/replayReader';
- import DomNodesChart from 'sentry/views/replays/detail/memoryPanel/domNodesChart';
- import MemoryChart from 'sentry/views/replays/detail/memoryPanel/memoryChart';
- function useCountDomNodes({replay}: {replay: null | ReplayReader}) {
- return useQuery(
- ['countDomNodes', replay],
- () =>
- countDomNodes({
- frames: replay?.getRRWebMutations(),
- rrwebEvents: replay?.getRRWebFrames(),
- startTimestampMs: replay?.getStartTimestampMs() ?? 0,
- }),
- {enabled: Boolean(replay), cacheTime: Infinity}
- );
- }
- export default function MemoryPanel() {
- const {
- currentTime,
- currentHoverTime,
- isFetching,
- replay,
- setCurrentHoverTime,
- setCurrentTime,
- } = useReplayContext();
- const memoryFrames = replay?.getMemoryFrames();
- const {data: frameToCount} = useCountDomNodes({replay});
- const domNodeData = useMemo(
- () => Array.from(frameToCount?.values() || []),
- [frameToCount]
- );
- const memoryChart =
- !replay || isFetching ? (
- <Placeholder height="100%" />
- ) : !replay || !memoryFrames?.length ? (
- <EmptyMessage
- data-test-id="replay-details-memory-tab"
- title={t('No memory metrics found')}
- description={t(
- 'Memory metrics are only captured within Chromium based browser sessions.'
- )}
- />
- ) : (
- <Fragment>
- <ChartTitle>{t('Heap Size')}</ChartTitle>
- <MemoryChart
- currentHoverTime={currentHoverTime}
- currentTime={currentTime}
- durationMs={replay.getDurationMs()}
- memoryFrames={memoryFrames}
- setCurrentHoverTime={setCurrentHoverTime}
- setCurrentTime={setCurrentTime}
- startTimestampMs={replay.getStartTimestampMs()}
- />
- </Fragment>
- );
- const domNodesChart =
- !replay || isFetching ? (
- <Placeholder height="100%" />
- ) : (
- <Fragment>
- <ChartTitle>{t('DOM Nodes')}</ChartTitle>
- <DomNodesChart
- currentHoverTime={currentHoverTime}
- currentTime={currentTime}
- durationMs={replay.getDurationMs()}
- datapoints={domNodeData}
- setCurrentHoverTime={setCurrentHoverTime}
- setCurrentTime={setCurrentTime}
- startTimestampMs={replay.getStartTimestampMs()}
- />
- </Fragment>
- );
- return (
- <Grid>
- <ChartWrapper>{memoryChart}</ChartWrapper>
- <ChartWrapper>{domNodesChart}</ChartWrapper>
- </Grid>
- );
- }
- const Grid = styled('div')`
- display: grid;
- grid-template-rows: 1fr 1fr;
- grid-template-columns: 1fr;
- gap: ${space(1)};
- justify-content: center;
- height: 100%;
- `;
- const ChartWrapper = styled('div')`
- border: 1px solid ${p => p.theme.border};
- border-radius: ${space(0.5)};
- padding: ${space(1)};
- overflow: hidden;
- display: flex;
- flex-direction: column;
- & > * {
- flex-grow: 1;
- }
- `;
- const ChartTitle = styled('h5')`
- font-size: ${p => p.theme.fontSizeLarge};
- font-weight: ${p => p.theme.text.cardTitle.fontWeight};
- line-height: ${p => p.theme.text.cardTitle.lineHeight};
- color: ${p => p.theme.subText};
- flex: 0 1 auto;
- margin: 0;
- `;
|