transactionSamplesTable.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import DateTime from 'sentry/components/dateTime';
  2. import Duration from 'sentry/components/duration';
  3. import GridEditable, {GridColumnHeader} from 'sentry/components/gridEditable';
  4. import Link from 'sentry/components/links/link';
  5. import EventView from 'sentry/utils/discover/eventView';
  6. import {useLocation} from 'sentry/utils/useLocation';
  7. import {DurationComparisonCell} from 'sentry/views/starfish/components/samplesTable/common';
  8. import useSlowMedianFastSamplesQuery from 'sentry/views/starfish/components/samplesTable/useSlowMedianFastSamplesQuery';
  9. import {
  10. OverflowEllipsisTextContainer,
  11. TextAlignLeft,
  12. TextAlignRight,
  13. } from 'sentry/views/starfish/components/textAlign';
  14. type Keys = 'id' | 'profile_id' | 'timestamp' | 'transaction.duration' | 'p95_comparison';
  15. type TableColumnHeader = GridColumnHeader<Keys>;
  16. const COLUMN_ORDER: TableColumnHeader[] = [
  17. {
  18. key: 'id',
  19. name: 'Event ID',
  20. width: 200,
  21. },
  22. {
  23. key: 'profile_id',
  24. name: 'Profile ID',
  25. width: 200,
  26. },
  27. {
  28. key: 'timestamp',
  29. name: 'Timestamp',
  30. width: 300,
  31. },
  32. {
  33. key: 'transaction.duration',
  34. name: 'Duration',
  35. width: 200,
  36. },
  37. {
  38. key: 'p95_comparison',
  39. name: 'Compared to P95',
  40. width: 200,
  41. },
  42. ];
  43. type Props = {
  44. eventView: EventView;
  45. };
  46. type DataRow = {
  47. id: string;
  48. profile_id: string;
  49. timestamp: string;
  50. 'transaction.duration': number;
  51. };
  52. export function TransactionSamplesTable({eventView}: Props) {
  53. const location = useLocation();
  54. const {isLoading, data, aggregatesData} = useSlowMedianFastSamplesQuery(eventView);
  55. function renderHeadCell(column: GridColumnHeader): React.ReactNode {
  56. if (column.key === 'p95_comparison') {
  57. return (
  58. <TextAlignRight>
  59. <OverflowEllipsisTextContainer>{column.name}</OverflowEllipsisTextContainer>
  60. </TextAlignRight>
  61. );
  62. }
  63. return <OverflowEllipsisTextContainer>{column.name}</OverflowEllipsisTextContainer>;
  64. }
  65. function renderBodyCell(column: TableColumnHeader, row: DataRow): React.ReactNode {
  66. if (column.key === 'id') {
  67. return (
  68. <Link to={`/performance/${row['project.name']}:${row.id}`}>
  69. {row.id.slice(0, 8)}
  70. </Link>
  71. );
  72. }
  73. if (column.key === 'profile_id') {
  74. return row.profile_id ? (
  75. <Link
  76. to={`/profiling/profile/${row['project.name']}/${row.profile_id}/flamechart/`}
  77. >
  78. {row.profile_id.slice(0, 8)}
  79. </Link>
  80. ) : (
  81. '(no value)'
  82. );
  83. }
  84. if (column.key === 'transaction.duration') {
  85. return (
  86. <Duration
  87. seconds={row['transaction.duration'] / 1000}
  88. fixedDigits={2}
  89. abbreviation
  90. />
  91. );
  92. }
  93. if (column.key === 'timestamp') {
  94. return <DateTime date={row[column.key]} year timeZone seconds />;
  95. }
  96. if (column.key === 'p95_comparison') {
  97. return (
  98. <DurationComparisonCell
  99. duration={row['transaction.duration']}
  100. p95={(aggregatesData?.['p95(transaction.duration)'] as number) ?? 0}
  101. />
  102. );
  103. }
  104. return <TextAlignLeft>{row[column.key]}</TextAlignLeft>;
  105. }
  106. return (
  107. <GridEditable
  108. isLoading={isLoading}
  109. data={data as DataRow[]}
  110. columnOrder={COLUMN_ORDER}
  111. columnSortBy={[]}
  112. location={location}
  113. grid={{
  114. renderHeadCell,
  115. renderBodyCell,
  116. }}
  117. />
  118. );
  119. }