123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import {Fragment, ReactElement, useMemo} from 'react';
- import styled from '@emotion/styled';
- import {FlamegraphOptionsMenu} from 'sentry/components/profiling/flamegraphOptionsMenu';
- import {FlamegraphSearch} from 'sentry/components/profiling/flamegraphSearch';
- import {FlamegraphToolbar} from 'sentry/components/profiling/flamegraphToolbar';
- import {FlamegraphViewSelectMenu} from 'sentry/components/profiling/flamegraphViewSelectMenu';
- import {FlamegraphZoomView} from 'sentry/components/profiling/flamegraphZoomView';
- import {FlamegraphZoomViewMinimap} from 'sentry/components/profiling/flamegraphZoomViewMinimap';
- import {
- ProfileDragDropImport,
- ProfileDragDropImportProps,
- } from 'sentry/components/profiling/profileDragDropImport';
- import {ThreadMenuSelector} from 'sentry/components/profiling/threadSelector';
- import {CanvasPoolManager} from 'sentry/utils/profiling/canvasScheduler';
- import {Flamegraph as FlamegraphModel} from 'sentry/utils/profiling/flamegraph';
- import {FlamegraphTheme} from 'sentry/utils/profiling/flamegraph/flamegraphTheme';
- import {useFlamegraphPreferences} from 'sentry/utils/profiling/flamegraph/useFlamegraphPreferences';
- import {useFlamegraphProfiles} from 'sentry/utils/profiling/flamegraph/useFlamegraphProfiles';
- import {useFlamegraphTheme} from 'sentry/utils/profiling/flamegraph/useFlamegraphTheme';
- import {Rect} from 'sentry/utils/profiling/gl/utils';
- import {ProfileGroup} from 'sentry/utils/profiling/profile/importProfile';
- import {Profile} from 'sentry/utils/profiling/profile/profile';
- function getTransactionConfigSpace(profiles: Profile[]): Rect {
- const startedAt = Math.min(...profiles.map(p => p.startedAt));
- const endedAt = Math.max(...profiles.map(p => p.endedAt));
- return new Rect(startedAt, 0, endedAt - startedAt, 0);
- }
- interface FlamegraphProps {
- onImport: ProfileDragDropImportProps['onImport'];
- profiles: ProfileGroup;
- }
- function Flamegraph(props: FlamegraphProps): ReactElement {
- const flamegraphTheme = useFlamegraphTheme();
- const [{sorting, view, xAxis}, dispatch] = useFlamegraphPreferences();
- const [{activeProfileIndex}, dispatchActiveProfileIndex] = useFlamegraphProfiles();
- const canvasPoolManager = useMemo(() => new CanvasPoolManager(), []);
- const flamegraph = useMemo(() => {
- if (
- !props.profiles.profiles[activeProfileIndex ?? props.profiles.activeProfileIndex]
- ) {
- // This could happen if activeProfileIndex was initialized from query string, but for some
- // reason the profile was removed from the list of profiles.
- return FlamegraphModel.Empty();
- }
- // if the activeProfileIndex is null, use the activeProfileIndex from the profile group
- return new FlamegraphModel(
- props.profiles.profiles[activeProfileIndex ?? props.profiles.activeProfileIndex],
- activeProfileIndex ?? props.profiles.activeProfileIndex,
- {
- inverted: view === 'bottom up',
- leftHeavy: sorting === 'left heavy',
- configSpace:
- xAxis === 'transaction'
- ? getTransactionConfigSpace(props.profiles.profiles)
- : undefined,
- }
- );
- }, [props.profiles, activeProfileIndex, sorting, xAxis, view]);
- return (
- <Fragment>
- <FlamegraphToolbar>
- <ThreadMenuSelector
- profileGroup={props.profiles}
- activeProfileIndex={flamegraph.profileIndex}
- onProfileIndexChange={index =>
- dispatchActiveProfileIndex({type: 'set active profile index', payload: index})
- }
- />
- <FlamegraphViewSelectMenu
- view={view}
- sorting={sorting}
- onSortingChange={s => {
- dispatch({type: 'set sorting', payload: s});
- }}
- onViewChange={v => {
- dispatch({type: 'set view', payload: v});
- }}
- />
- <FlamegraphSearch
- flamegraphs={[flamegraph]}
- canvasPoolManager={canvasPoolManager}
- />
- <FlamegraphOptionsMenu canvasPoolManager={canvasPoolManager} />
- </FlamegraphToolbar>
- <FlamegraphZoomViewMinimapContainer height={flamegraphTheme.SIZES.MINIMAP_HEIGHT}>
- <FlamegraphZoomViewMinimap
- flamegraph={flamegraph}
- canvasPoolManager={canvasPoolManager}
- />
- </FlamegraphZoomViewMinimapContainer>
- <FlamegraphZoomViewContainer>
- <ProfileDragDropImport onImport={props.onImport}>
- <FlamegraphZoomView
- flamegraph={flamegraph}
- canvasPoolManager={canvasPoolManager}
- />
- </ProfileDragDropImport>
- </FlamegraphZoomViewContainer>
- </Fragment>
- );
- }
- const FlamegraphZoomViewMinimapContainer = styled('div')<{
- height: FlamegraphTheme['SIZES']['MINIMAP_HEIGHT'];
- }>`
- position: relative;
- height: ${p => p.height}px;
- flex-shrink: 0;
- `;
- const FlamegraphZoomViewContainer = styled('div')`
- position: relative;
- flex: 1 1 100%;
- `;
- export {Flamegraph};
|