import {Fragment} from 'react'; import {useTheme} from '@emotion/react'; import styled from '@emotion/styled'; import {HeaderTitle} from 'sentry/components/charts/styles'; import ProjectBadge from 'sentry/components/idBadge/projectBadge'; import ExternalLink from 'sentry/components/links/externalLink'; import {Panel, PanelBody} from 'sentry/components/panels'; import Placeholder from 'sentry/components/placeholder'; import QuestionTooltip from 'sentry/components/questionTooltip'; import Tooltip from 'sentry/components/tooltip'; import {t, tct} from 'sentry/locale'; import space from 'sentry/styles/space'; import {Organization, Project} from 'sentry/types'; import {percent} from 'sentry/utils'; import {formatPercentage} from 'sentry/utils/formatters'; import useProjects from 'sentry/utils/useProjects'; import ColorBar from 'sentry/views/performance/vitalDetail/colorBar'; import {useDistribution} from './utils/useDistribution'; import {SERVER_SIDE_SAMPLING_DOC_LINK} from './utils'; type Props = { orgSlug: Organization['slug']; }; export function SamplingBreakdown({orgSlug}: Props) { const theme = useTheme(); const {distribution, loading} = useDistribution(); const projectBreakdown = distribution?.projectBreakdown; const {projects} = useProjects({ slugs: projectBreakdown?.map(project => project.project) ?? [], orgId: orgSlug, }); const totalCount = projectBreakdown?.reduce( (acc, project) => acc + project['count()'], 0 ); const projectsWithPercentages = projects .map(project => ({ project, percentage: percent( projectBreakdown?.find(pb => pb.project === project.slug)?.['count()'] ?? 0, totalCount ?? 0 ), })) .sort((a, z) => z.percentage - a.percentage); function projectWithPercentage(project: Project, percentage: number) { return ( {formatPercentage(percentage / 100)} ); } return ( {t('Transaction Breakdown')} ), } )} size="sm" isHoverable /> {loading ? ( ) : ( ({ color: theme.charts.getColorPalette(projectsWithPercentages.length)[ index ], percent: percentage, renderBarStatus: (barStatus, key) => ( {barStatus} ), }))} /> {projectsWithPercentages.length ? ( {projectsWithPercentages.map(({project, percentage}) => projectWithPercentage(project, percentage) )} ) : ( {tct( 'This project made no [samplingDecisions] within the last 30 days.', { samplingDecisions: ( ), } )} showUnderline isHoverable > {t('sampling decisions')} ), } )} )} )} ); } const TitleWrapper = styled('div')` display: flex; gap: ${space(1)}; align-items: center; margin-bottom: ${space(1.5)}; `; const Projects = styled('div')` display: flex; flex-wrap: wrap; gap: ${space(1.5)}; justify-content: flex-start; align-items: center; margin-top: ${space(1.5)}; `; const ProjectWithPercentage = styled('div')` display: grid; grid-template-columns: 1fr max-content; align-items: center; gap: ${space(0.5)}; color: ${p => p.theme.subText}; `; const EmptyMessage = styled('div')` display: flex; align-items: center; min-height: 25px; color: ${p => p.theme.subText}; `; const StyledProjectBadge = styled(ProjectBadge)` max-width: 100%; overflow: hidden; `;