messageSpanSamplesTable.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import type {ComponentProps} from 'react';
  2. import styled from '@emotion/styled';
  3. import type {Location} from 'history';
  4. import GridEditable, {
  5. COL_WIDTH_UNDEFINED,
  6. type GridColumnHeader,
  7. } from 'sentry/components/gridEditable';
  8. import {t} from 'sentry/locale';
  9. import type {Organization} from 'sentry/types/organization';
  10. import type {EventsMetaType} from 'sentry/utils/discover/eventView';
  11. import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
  12. import {useLocation} from 'sentry/utils/useLocation';
  13. import useOrganization from 'sentry/utils/useOrganization';
  14. import {renderHeadCell} from 'sentry/views/starfish/components/tableCells/renderHeadCell';
  15. import {SpanIdCell} from 'sentry/views/starfish/components/tableCells/spanIdCell';
  16. import type {IndexedResponse} from 'sentry/views/starfish/types';
  17. import {SpanIndexedField} from 'sentry/views/starfish/types';
  18. type DataRowKeys =
  19. | SpanIndexedField.PROJECT
  20. | SpanIndexedField.TRANSACTION_ID
  21. | SpanIndexedField.TRACE
  22. | SpanIndexedField.TIMESTAMP
  23. | SpanIndexedField.ID
  24. | SpanIndexedField.SPAN_DESCRIPTION
  25. | SpanIndexedField.RESPONSE_CODE;
  26. type ColumnKeys =
  27. | SpanIndexedField.ID
  28. | SpanIndexedField.MESSAGE_ID
  29. | SpanIndexedField.MESSAGE_SIZE
  30. | SpanIndexedField.MESSAGE_STATUS
  31. | SpanIndexedField.SPAN_SELF_TIME;
  32. type DataRow = Pick<IndexedResponse, DataRowKeys>;
  33. type Column = GridColumnHeader<ColumnKeys>;
  34. const COLUMN_ORDER: Column[] = [
  35. {
  36. key: SpanIndexedField.ID,
  37. name: t('Span ID'),
  38. width: COL_WIDTH_UNDEFINED,
  39. },
  40. {
  41. key: SpanIndexedField.MESSAGE_ID,
  42. name: t('Message ID'),
  43. width: COL_WIDTH_UNDEFINED,
  44. },
  45. {
  46. key: SpanIndexedField.SPAN_SELF_TIME,
  47. name: t('Processing Latency'),
  48. width: COL_WIDTH_UNDEFINED,
  49. },
  50. {
  51. key: SpanIndexedField.MESSAGE_SIZE,
  52. name: t('Message Size'),
  53. width: COL_WIDTH_UNDEFINED,
  54. },
  55. {
  56. key: SpanIndexedField.MESSAGE_STATUS,
  57. name: t('Status'),
  58. width: COL_WIDTH_UNDEFINED,
  59. },
  60. ];
  61. interface Props {
  62. data: DataRow[];
  63. isLoading: boolean;
  64. error?: Error | null;
  65. highlightedSpanId?: string;
  66. meta?: EventsMetaType;
  67. onSampleMouseOut?: ComponentProps<typeof GridEditable>['onRowMouseOut'];
  68. onSampleMouseOver?: ComponentProps<typeof GridEditable>['onRowMouseOver'];
  69. }
  70. export function MessageSpanSamplesTable({
  71. data,
  72. isLoading,
  73. error,
  74. meta,
  75. onSampleMouseOver,
  76. onSampleMouseOut,
  77. highlightedSpanId,
  78. }: Props) {
  79. const location = useLocation();
  80. const organization = useOrganization();
  81. return (
  82. <GridEditable
  83. aria-label={t('Span Samples')}
  84. isLoading={isLoading}
  85. error={error}
  86. data={data}
  87. columnOrder={COLUMN_ORDER}
  88. columnSortBy={[]}
  89. grid={{
  90. renderHeadCell: col =>
  91. renderHeadCell({
  92. column: col,
  93. location,
  94. }),
  95. renderBodyCell: (column, row) =>
  96. renderBodyCell(column, row, meta, location, organization),
  97. }}
  98. highlightedRowKey={data.findIndex(row => row.span_id === highlightedSpanId)}
  99. onRowMouseOver={onSampleMouseOver}
  100. onRowMouseOut={onSampleMouseOut}
  101. location={location}
  102. />
  103. );
  104. }
  105. function renderBodyCell(
  106. column: Column,
  107. row: DataRow,
  108. meta: EventsMetaType | undefined,
  109. location: Location,
  110. organization: Organization
  111. ) {
  112. const key = column.key;
  113. if (row[key] === undefined) {
  114. return (
  115. <AlignRight>
  116. <NoValue>{' \u2014 '}</NoValue>
  117. </AlignRight>
  118. );
  119. }
  120. if (key === SpanIndexedField.ID) {
  121. return (
  122. <SpanIdCell
  123. projectSlug={row.project}
  124. traceId={row.trace}
  125. timestamp={row.timestamp}
  126. transactionId={row[SpanIndexedField.TRANSACTION_ID]}
  127. spanId={row[SpanIndexedField.ID]}
  128. />
  129. );
  130. }
  131. if (!meta?.fields) {
  132. return row[column.key];
  133. }
  134. const renderer = getFieldRenderer(column.key, meta.fields, false);
  135. return renderer(row, {
  136. location,
  137. organization,
  138. unit: meta.units?.[column.key],
  139. });
  140. }
  141. const AlignRight = styled('span')`
  142. text-align: right;
  143. `;
  144. const NoValue = styled('span')`
  145. color: ${p => p.theme.gray300};
  146. `;