import {Fragment, useMemo, useRef} from 'react'; import styled from '@emotion/styled'; import EmptyStateWarning from 'sentry/components/emptyStateWarning'; import {GridResizer} from 'sentry/components/gridEditable/styles'; import Link from 'sentry/components/links/link'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import Pagination from 'sentry/components/pagination'; import {Tooltip} from 'sentry/components/tooltip'; import {CHART_PALETTE} from 'sentry/constants/chartPalette'; import {IconArrow} from 'sentry/icons/iconArrow'; import {IconStack} from 'sentry/icons/iconStack'; import {IconWarning} from 'sentry/icons/iconWarning'; import {t} from 'sentry/locale'; import type {Confidence} from 'sentry/types/organization'; import {defined} from 'sentry/utils'; import { fieldAlignment, parseFunction, prettifyParsedFunction, } from 'sentry/utils/discover/fields'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import useProjects from 'sentry/utils/useProjects'; import { Table, TableBody, TableBodyCell, TableHead, TableHeadCell, TableHeadCellContent, TableRow, TableStatus, useTableStyles, } from 'sentry/views/explore/components/table'; import { useExploreDataset, useExploreGroupBys, useExploreQuery, useExploreSortBys, useExploreTitle, useExploreVisualizes, useSetExploreSortBys, } from 'sentry/views/explore/contexts/pageParamsContext'; import {useSpanTags} from 'sentry/views/explore/contexts/spanTagsContext'; import {useAnalytics} from 'sentry/views/explore/hooks/useAnalytics'; import type {AggregatesTableResult} from 'sentry/views/explore/hooks/useExploreAggregatesTable'; import {TOP_EVENTS_LIMIT, useTopEvents} from 'sentry/views/explore/hooks/useTopEvents'; import {viewSamplesTarget} from 'sentry/views/explore/utils'; import {FieldRenderer} from './fieldRenderer'; interface AggregatesTableProps { aggregatesTableResult: AggregatesTableResult; confidences: Confidence[]; } export function AggregatesTable({ aggregatesTableResult, confidences, }: AggregatesTableProps) { const location = useLocation(); const organization = useOrganization(); const {projects} = useProjects(); const topEvents = useTopEvents(); const title = useExploreTitle(); const dataset = useExploreDataset(); const groupBys = useExploreGroupBys(); const visualizes = useExploreVisualizes(); const {result, eventView, fields} = aggregatesTableResult; const sorts = useExploreSortBys(); const setSorts = useSetExploreSortBys(); const query = useExploreQuery(); const columns = useMemo(() => eventView.getColumns(), [eventView]); useAnalytics({ dataset, resultLength: result.data?.length, resultMode: 'aggregates', resultStatus: result.status, visualizes, organization, columns: groupBys, userQuery: query, confidences, title, }); const tableRef = useRef(null); const {initialTableStyles, onResizeMouseDown} = useTableStyles(fields, tableRef, { minimumColumnWidth: 50, prefixColumnWidth: 'min-content', }); const meta = result.meta ?? {}; const numberTags = useSpanTags('number'); const stringTags = useSpanTags('string'); return ( {fields.map((field, i) => { // Hide column names before alignment is determined if (result.isPending) { return ; } let label = field; const fieldType = meta.fields?.[field]; const align = fieldAlignment(field, fieldType); const tag = stringTags[field] ?? numberTags[field] ?? null; if (tag) { label = tag.name; } const func = parseFunction(field); if (func) { label = prettifyParsedFunction(func); } const direction = sorts.find(s => s.field === field)?.kind; function updateSort() { const kind = direction === 'desc' ? 'asc' : 'desc'; setSorts([{field, kind}]); } return ( {label} {defined(direction) && ( )} {i !== fields.length - 1 && ( onResizeMouseDown(e, i)} /> )} ); })} {result.isPending ? ( ) : result.isError ? ( ) : result.isFetched && result.data?.length ? ( result.data?.map((row, i) => { const target = viewSamplesTarget(location, query, groupBys, row, { projects, }); return ( {topEvents && i < topEvents && } {fields.map((field, j) => { return ( ); })} ); }) ) : (

{t('No spans found')}

)}
); } const TopResultsIndicator = styled('div')<{index: number}>` position: absolute; left: -1px; width: 9px; height: 16px; border-radius: 0 3px 3px 0; background-color: ${p => { return CHART_PALETTE[TOP_EVENTS_LIMIT - 1]![p.index]; }}; `; const StyledLink = styled(Link)` display: flex; `;