import {useCallback, useMemo} from 'react'; import styled from '@emotion/styled'; import CompactSelect from 'sentry/components/compactSelect'; import {IconList} from 'sentry/icons'; import {tn} from 'sentry/locale'; import space from 'sentry/styles/space'; import {SelectValue} from 'sentry/types'; import {defined} from 'sentry/utils'; import {FlamegraphState} from 'sentry/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphContext'; import {ProfileGroup} from 'sentry/utils/profiling/profile/importProfile'; import {Profile} from 'sentry/utils/profiling/profile/profile'; import {makeFormatter} from 'sentry/utils/profiling/units/units'; interface ThreadSelectorProps { onThreadIdChange: (threadId: Profile['threadId']) => void; profileGroup: ProfileGroup; threadId: FlamegraphState['profiles']['threadId']; } function ThreadMenuSelector({ threadId, onThreadIdChange, profileGroup, }: ThreadSelectorProps) { const options: SelectValue[] = useMemo(() => { return [...profileGroup.profiles].sort(compareProfiles).map(profile => { return { label: profile.name ? `tid (${profile.threadId}): ${profile.name}` : `tid (${profile.threadId})`, value: profile.threadId, disabled: profile.samples.length === 0, details: ( ), }; }); }, [profileGroup]); const handleChange: (opt: SelectValue) => void = useCallback( opt => { if (defined(opt)) { onThreadIdChange(opt.value); } }, [onThreadIdChange] ); return ( , size: 'xs', }} options={options} value={threadId} onChange={handleChange} isSearchable /> ); } interface ThreadLabelDetailsProps { duration: string; samples: number; } function ThreadLabelDetails(props: ThreadLabelDetailsProps) { return (
{props.duration}
{tn('%s sample', '%s samples', props.samples)}
); } type ProfileLight = { duration: Profile['duration']; name: Profile['name']; threadId: Profile['threadId']; }; function compareProfiles(a: ProfileLight, b: ProfileLight): number { if (!b.duration) { return -1; } if (!a.duration) { return 1; } if (a.name.startsWith('(tid') && b.name.startsWith('(tid')) { return -1; } if (a.name.startsWith('(tid')) { return -1; } if (b.name.startsWith('(tid')) { return -1; } if (a.name.includes('main')) { return -1; } if (b.name.includes('main')) { return 1; } return a.name > b.name ? -1 : 1; } const DetailsContainer = styled('div')` display: flex; flex-direction: row; justify-content: space-between; gap: ${space(1)}; `; export {ThreadMenuSelector};