fieldRenderer.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import styled from '@emotion/styled';
  2. import Link from 'sentry/components/links/link';
  3. import TimeSince from 'sentry/components/timeSince';
  4. import type {TableDataRow} from 'sentry/utils/discover/discoverQuery';
  5. import type {EventData, MetaType} from 'sentry/utils/discover/eventView';
  6. import EventView from 'sentry/utils/discover/eventView';
  7. import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
  8. import {Container} from 'sentry/utils/discover/styles';
  9. import {generateLinkToEventInTraceView} from 'sentry/utils/discover/urls';
  10. import {getShortEventId} from 'sentry/utils/events';
  11. import {generateProfileFlamechartRouteWithQuery} from 'sentry/utils/profiling/routes';
  12. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  13. import {useLocation} from 'sentry/utils/useLocation';
  14. import useOrganization from 'sentry/utils/useOrganization';
  15. import CellAction, {updateQuery} from 'sentry/views/discover/table/cellAction';
  16. import type {TableColumn} from 'sentry/views/discover/table/types';
  17. import {
  18. useExploreQuery,
  19. useSetExploreQuery,
  20. } from 'sentry/views/explore/contexts/pageParamsContext';
  21. import {TraceViewSources} from 'sentry/views/performance/newTraceDetails/traceHeader/breadcrumbs';
  22. import {getTraceDetailsUrl} from 'sentry/views/performance/traceDetails/utils';
  23. import {ALLOWED_CELL_ACTIONS} from '../components/table';
  24. interface FieldProps {
  25. column: TableColumn<keyof TableDataRow>;
  26. data: EventData;
  27. meta: MetaType;
  28. unit?: string;
  29. }
  30. export function FieldRenderer({data, meta, unit, column}: FieldProps) {
  31. const location = useLocation();
  32. const organization = useOrganization();
  33. const userQuery = useExploreQuery();
  34. const setUserQuery = useSetExploreQuery();
  35. const dateSelection = EventView.fromLocation(location).normalizeDateSelection(location);
  36. const query = new MutableSearch(userQuery);
  37. const field = column.name;
  38. const renderer = getExploreFieldRenderer(field, meta);
  39. let rendered = renderer(data, {
  40. location,
  41. organization,
  42. unit,
  43. });
  44. if (field === 'timestamp') {
  45. const date = new Date(data.timestamp);
  46. rendered = <StyledTimeSince unitStyle="extraShort" date={date} tooltipShowSeconds />;
  47. }
  48. if (field === 'trace') {
  49. const target = getTraceDetailsUrl({
  50. traceSlug: data.trace,
  51. timestamp: data.timestamp,
  52. organization,
  53. dateSelection,
  54. location,
  55. source: TraceViewSources.TRACES,
  56. });
  57. rendered = <Link to={target}>{rendered}</Link>;
  58. }
  59. if (['id', 'span_id', 'transaction.id'].includes(field)) {
  60. const spanId = field === 'transaction.id' ? undefined : data.span_id ?? data.id;
  61. const target = generateLinkToEventInTraceView({
  62. projectSlug: data.project,
  63. traceSlug: data.trace,
  64. timestamp: data.timestamp,
  65. targetId: data['transaction.span_id'],
  66. eventId: undefined,
  67. organization,
  68. location,
  69. spanId,
  70. source: TraceViewSources.TRACES,
  71. });
  72. rendered = <Link to={target}>{rendered}</Link>;
  73. }
  74. if (field === 'profile.id') {
  75. const target = generateProfileFlamechartRouteWithQuery({
  76. orgSlug: organization.slug,
  77. projectSlug: data.project,
  78. profileId: data['profile.id'],
  79. });
  80. rendered = <Link to={target}>{rendered}</Link>;
  81. }
  82. return (
  83. <CellAction
  84. column={column}
  85. dataRow={data as TableDataRow}
  86. handleCellAction={(actions, value) => {
  87. updateQuery(query, actions, column, value);
  88. setUserQuery(query.formatString());
  89. }}
  90. allowActions={ALLOWED_CELL_ACTIONS}
  91. >
  92. {rendered}
  93. </CellAction>
  94. );
  95. }
  96. function getExploreFieldRenderer(
  97. field: string,
  98. meta: MetaType
  99. ): ReturnType<typeof getFieldRenderer> {
  100. if (field === 'id' || field === 'span_id') {
  101. return eventIdRenderFunc(field);
  102. }
  103. return getFieldRenderer(field, meta, false);
  104. }
  105. function eventIdRenderFunc(field: string) {
  106. function renderer(data: EventData) {
  107. const spanId: string | unknown = data?.[field];
  108. if (typeof spanId !== 'string') {
  109. return null;
  110. }
  111. return <Container>{getShortEventId(spanId)}</Container>;
  112. }
  113. return renderer;
  114. }
  115. const StyledTimeSince = styled(TimeSince)`
  116. width: fit-content;
  117. `;