123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- import {useMemo} from 'react';
- import Count from 'sentry/components/count';
- import DateTime from 'sentry/components/dateTime';
- import GridEditable, {
- COL_WIDTH_UNDEFINED,
- GridColumnOrder,
- } from 'sentry/components/gridEditable';
- import ProjectBadge from 'sentry/components/idBadge/projectBadge';
- import Link from 'sentry/components/links/link';
- import PerformanceDuration from 'sentry/components/performanceDuration';
- import {t} from 'sentry/locale';
- import {ProfileTransaction} from 'sentry/types/profiling/core';
- import {defined} from 'sentry/utils';
- import {Container, NumberContainer} from 'sentry/utils/discover/styles';
- import {generateProfileSummaryRouteWithQuery} from 'sentry/utils/profiling/routes';
- import {renderTableHead} from 'sentry/utils/profiling/tableRenderer';
- import {useLocation} from 'sentry/utils/useLocation';
- import useOrganization from 'sentry/utils/useOrganization';
- import useProjects from 'sentry/utils/useProjects';
- interface ProfileTransactionsTableProps {
- error: string | null;
- isLoading: boolean;
- transactions: ProfileTransaction[];
- }
- function ProfileTransactionsTable(props: ProfileTransactionsTableProps) {
- const location = useLocation();
- const organization = useOrganization();
- const {projects} = useProjects();
- const transactions: TableDataRow[] = useMemo(() => {
- return props.transactions.map(transaction => {
- const project = projects.find(proj => proj.id === transaction.project_id);
- return {
- transaction: project ? (
- <Link
- to={generateProfileSummaryRouteWithQuery({
- location,
- orgSlug: organization.slug,
- projectSlug: project.slug,
- transaction: transaction.name,
- })}
- >
- {transaction.name}
- </Link>
- ) : (
- transaction.name
- ),
- count: transaction.profiles_count,
- project,
- p50: transaction.duration_ms.p50,
- p75: transaction.duration_ms.p75,
- p90: transaction.duration_ms.p90,
- p95: transaction.duration_ms.p95,
- p99: transaction.duration_ms.p99,
- lastSeen: transaction.last_profile_at,
- };
- });
- }, [props.transactions, location, organization, projects]);
- return (
- <GridEditable
- isLoading={props.isLoading}
- error={props.error}
- data={transactions}
- columnOrder={COLUMN_ORDER.map(key => COLUMNS[key])}
- columnSortBy={[]}
- grid={{
- renderHeadCell: renderTableHead({rightAlignedColumns: RIGHT_ALIGNED_COLUMNS}),
- renderBodyCell: renderTableBody,
- }}
- location={location}
- />
- );
- }
- const RIGHT_ALIGNED_COLUMNS = new Set<TableColumnKey>([
- 'count',
- 'p50',
- 'p75',
- 'p90',
- 'p95',
- 'p99',
- ]);
- function renderTableBody(
- column: TableColumn,
- dataRow: TableDataRow,
- rowIndex: number,
- columnIndex: number
- ) {
- return (
- <ProfilingTransactionsTableCell
- column={column}
- dataRow={dataRow}
- rowIndex={rowIndex}
- columnIndex={columnIndex}
- />
- );
- }
- interface ProfilingTransactionsTableCellProps {
- column: TableColumn;
- columnIndex: number;
- dataRow: TableDataRow;
- rowIndex: number;
- }
- function ProfilingTransactionsTableCell({
- column,
- dataRow,
- }: ProfilingTransactionsTableCellProps) {
- const value = dataRow[column.key];
- switch (column.key) {
- case 'project':
- if (!defined(value)) {
- // should never happen but just in case
- return <Container>{t('n/a')}</Container>;
- }
- return (
- <Container>
- <ProjectBadge project={value} avatarSize={16} />
- </Container>
- );
- case 'count':
- return (
- <NumberContainer>
- <Count value={value} />
- </NumberContainer>
- );
- case 'p50':
- case 'p75':
- case 'p90':
- case 'p95':
- case 'p99':
- return (
- <NumberContainer>
- <PerformanceDuration milliseconds={value} abbreviation />
- </NumberContainer>
- );
- case 'lastSeen':
- return (
- <Container>
- <DateTime date={value} />
- </Container>
- );
- default:
- return <Container>{value}</Container>;
- }
- }
- type TableColumnKey =
- | 'transaction'
- | 'count'
- | 'project'
- | 'p50'
- | 'p75'
- | 'p90'
- | 'p95'
- | 'p99'
- | 'lastSeen';
- type TableDataRow = Record<TableColumnKey, any>;
- type TableColumn = GridColumnOrder<TableColumnKey>;
- const COLUMN_ORDER: TableColumnKey[] = [
- 'transaction',
- 'project',
- 'lastSeen',
- 'p75',
- 'p95',
- 'count',
- ];
- const COLUMNS: Record<TableColumnKey, TableColumn> = {
- transaction: {
- key: 'transaction',
- name: t('Transaction'),
- width: COL_WIDTH_UNDEFINED,
- },
- count: {
- key: 'count',
- name: t('Count'),
- width: COL_WIDTH_UNDEFINED,
- },
- project: {
- key: 'project',
- name: t('Project'),
- width: COL_WIDTH_UNDEFINED,
- },
- p50: {
- key: 'p50',
- name: t('P50'),
- width: COL_WIDTH_UNDEFINED,
- },
- p75: {
- key: 'p75',
- name: t('P75'),
- width: COL_WIDTH_UNDEFINED,
- },
- p90: {
- key: 'p90',
- name: t('P90'),
- width: COL_WIDTH_UNDEFINED,
- },
- p95: {
- key: 'p95',
- name: t('P95'),
- width: COL_WIDTH_UNDEFINED,
- },
- p99: {
- key: 'p99',
- name: t('P99'),
- width: COL_WIDTH_UNDEFINED,
- },
- lastSeen: {
- key: 'lastSeen',
- name: t('Last Seen'),
- width: COL_WIDTH_UNDEFINED,
- },
- };
- export {ProfileTransactionsTable};
|