import type {Location} from 'history'; import type {GridColumnHeader} from 'sentry/components/gridEditable'; import GridEditable, {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable'; import type {CursorHandler} from 'sentry/components/pagination'; import Pagination from 'sentry/components/pagination'; import {t} from 'sentry/locale'; import type {Organization} from 'sentry/types/organization'; import {trackAnalytics} from 'sentry/utils/analytics'; import {browserHistory} from 'sentry/utils/browserHistory'; import type {EventsMetaType} from 'sentry/utils/discover/eventView'; import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers'; import type {Sort} from 'sentry/utils/discover/fields'; import {RATE_UNIT_TITLE, RateUnit} from 'sentry/utils/discover/fields'; import {VisuallyCompleteWithData} from 'sentry/utils/performanceForSentry'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import {renderHeadCell} from 'sentry/views/insights/common/components/tableCells/renderHeadCell'; import {SpanDescriptionCell} from 'sentry/views/insights/common/components/tableCells/spanDescriptionCell'; import {QueryParameterNames} from 'sentry/views/insights/common/views/queryParameters'; import {DataTitles} from 'sentry/views/insights/common/views/spans/types'; import type {SpanMetricsResponse} from 'sentry/views/insights/types'; import {ModuleName} from 'sentry/views/insights/types'; type Row = Pick< SpanMetricsResponse, | 'project.id' | 'span.description' | 'span.group' | 'span.action' | 'spm()' | 'avg(span.self_time)' | 'sum(span.self_time)' | 'time_spent_percentage()' >; type Column = GridColumnHeader< 'span.description' | 'spm()' | 'avg(span.self_time)' | 'time_spent_percentage()' >; const COLUMN_ORDER: Column[] = [ { key: 'span.description', name: t('Query Description'), width: COL_WIDTH_UNDEFINED, }, { key: 'spm()', name: `${t('Queries')} ${RATE_UNIT_TITLE[RateUnit.PER_MINUTE]}`, width: COL_WIDTH_UNDEFINED, }, { key: `avg(span.self_time)`, name: DataTitles.avg, width: COL_WIDTH_UNDEFINED, }, { key: 'time_spent_percentage()', name: DataTitles.timeSpent, width: COL_WIDTH_UNDEFINED, }, ]; const SORTABLE_FIELDS = ['avg(span.self_time)', 'spm()', 'time_spent_percentage()']; type ValidSort = Sort & { field: 'spm()' | 'avg(span.self_time)' | 'time_spent_percentage()'; }; export function isAValidSort(sort: Sort): sort is ValidSort { return (SORTABLE_FIELDS as unknown as string[]).includes(sort.field); } interface Props { response: { data: Row[]; isLoading: boolean; error?: Error | null; meta?: EventsMetaType; pageLinks?: string; }; sort: ValidSort; system: string; } export function QueriesTable({response, sort, system}: Props) { const {data, isLoading, meta, pageLinks} = response; const location = useLocation(); const organization = useOrganization(); const handleCursor: CursorHandler = (newCursor, pathname, query) => { browserHistory.push({ pathname, query: {...query, [QueryParameterNames.SPANS_CURSOR]: newCursor}, }); }; return ( 0} isLoading={isLoading} > renderHeadCell({ column, sort, location, sortParameterName: QueryParameterNames.SPANS_SORT, }), renderBodyCell: (column, row) => renderBodyCell(column, row, meta, location, organization, system), }} /> { trackAnalytics('insight.general.table_paginate', { organization, source: ModuleName.DB, direction, }); }} /> ); } function renderBodyCell( column: Column, row: Row, meta: EventsMetaType | undefined, location: Location, organization: Organization, system: string ) { if (column.key === 'span.description') { return ( ); } if (!meta || !meta?.fields) { return row[column.key]; } const renderer = getFieldRenderer(column.key, meta.fields, false); const rendered = renderer(row, { location, organization, unit: meta.units?.[column.key], }); return rendered; }