transactionSamplesTable.tsx 3.8 KB

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