utils.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import {Location, LocationDescriptor} from 'history';
  2. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  3. import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
  4. import {OrganizationSummary} from 'sentry/types';
  5. import {Event} from 'sentry/types/event';
  6. import {defined} from 'sentry/utils';
  7. import EventView from 'sentry/utils/discover/eventView';
  8. import {
  9. eventDetailsRouteWithEventView,
  10. generateEventSlug,
  11. } from 'sentry/utils/discover/urls';
  12. import {
  13. EventLite,
  14. QuickTraceEvent,
  15. TraceError,
  16. } from 'sentry/utils/performance/quickTrace/types';
  17. import {getTraceTimeRangeFromEvent} from 'sentry/utils/performance/quickTrace/utils';
  18. import {getTransactionDetailsUrl} from 'sentry/utils/performance/urls';
  19. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  20. import {getTraceDetailsUrl} from 'sentry/views/performance/traceDetails/utils';
  21. export function isQuickTraceEvent(
  22. event: QuickTraceEvent | TraceError
  23. ): event is QuickTraceEvent {
  24. return defined((event as QuickTraceEvent)['transaction.duration']);
  25. }
  26. export type ErrorDestination = 'discover' | 'issue';
  27. export type TransactionDestination = 'discover' | 'performance';
  28. export function generateIssueEventTarget(
  29. event: TraceError,
  30. organization: OrganizationSummary
  31. ): LocationDescriptor {
  32. return `/organizations/${organization.slug}/issues/${event.issue_id}/events/${event.event_id}`;
  33. }
  34. function generatePerformanceEventTarget(
  35. event: EventLite,
  36. organization: OrganizationSummary,
  37. location: Location
  38. ): LocationDescriptor {
  39. const eventSlug = generateEventSlug({
  40. id: event.event_id,
  41. project: event.project_slug,
  42. });
  43. const query = {
  44. ...location.query,
  45. project: String(event.project_id),
  46. };
  47. return getTransactionDetailsUrl(organization.slug, eventSlug, event.transaction, query);
  48. }
  49. function generateDiscoverEventTarget(
  50. event: EventLite | TraceError,
  51. organization: OrganizationSummary,
  52. location: Location
  53. ): LocationDescriptor {
  54. const eventSlug = generateEventSlug({
  55. id: event.event_id,
  56. project: event.project_slug,
  57. });
  58. const newLocation = {
  59. ...location,
  60. query: {
  61. ...location.query,
  62. project: String(event.project_id),
  63. },
  64. };
  65. return eventDetailsRouteWithEventView({
  66. orgSlug: organization.slug,
  67. eventSlug,
  68. eventView: EventView.fromLocation(newLocation),
  69. });
  70. }
  71. export function generateSingleErrorTarget(
  72. event: TraceError,
  73. organization: OrganizationSummary,
  74. location: Location,
  75. destination: ErrorDestination
  76. ): LocationDescriptor {
  77. switch (destination) {
  78. case 'issue':
  79. return generateIssueEventTarget(event, organization);
  80. case 'discover':
  81. default:
  82. return generateDiscoverEventTarget(event, organization, location);
  83. }
  84. }
  85. export function generateSingleTransactionTarget(
  86. event: EventLite,
  87. organization: OrganizationSummary,
  88. location: Location,
  89. destination: TransactionDestination
  90. ): LocationDescriptor {
  91. switch (destination) {
  92. case 'performance':
  93. return generatePerformanceEventTarget(event, organization, location);
  94. case 'discover':
  95. default:
  96. return generateDiscoverEventTarget(event, organization, location);
  97. }
  98. }
  99. export function generateMultiTransactionsTarget(
  100. currentEvent: Event,
  101. events: EventLite[],
  102. organization: OrganizationSummary,
  103. groupType: 'Ancestor' | 'Children' | 'Descendant'
  104. ): LocationDescriptor {
  105. const queryResults = new MutableSearch([]);
  106. const eventIds = events.map(child => child.event_id);
  107. for (let i = 0; i < eventIds.length; i++) {
  108. queryResults.addOp(i === 0 ? '(' : 'OR');
  109. queryResults.addFreeText(`id:${eventIds[i]}`);
  110. if (i === eventIds.length - 1) {
  111. queryResults.addOp(')');
  112. }
  113. }
  114. const {start, end} = getTraceTimeRangeFromEvent(currentEvent);
  115. const traceEventView = EventView.fromSavedQuery({
  116. id: undefined,
  117. name: `${groupType} Transactions of Event ID ${currentEvent.id}`,
  118. fields: ['transaction', 'project', 'trace.span', 'transaction.duration', 'timestamp'],
  119. orderby: '-timestamp',
  120. query: queryResults.formatString(),
  121. projects: [...new Set(events.map(child => child.project_id))],
  122. version: 2,
  123. start,
  124. end,
  125. });
  126. return traceEventView.getResultsViewUrlTarget(organization.slug);
  127. }
  128. export function generateTraceTarget(
  129. event: Event,
  130. organization: OrganizationSummary
  131. ): LocationDescriptor {
  132. const traceId = event.contexts?.trace?.trace_id ?? '';
  133. const dateSelection = normalizeDateTimeParams(getTraceTimeRangeFromEvent(event));
  134. if (organization.features.includes('performance-view')) {
  135. // TODO(txiao): Should this persist the current query when going to trace view?
  136. return getTraceDetailsUrl(organization, traceId, dateSelection, {});
  137. }
  138. const eventView = EventView.fromSavedQuery({
  139. id: undefined,
  140. name: `Events with Trace ID ${traceId}`,
  141. fields: ['title', 'event.type', 'project', 'trace.span', 'timestamp'],
  142. orderby: '-timestamp',
  143. query: `trace:${traceId}`,
  144. projects: organization.features.includes('global-views')
  145. ? [ALL_ACCESS_PROJECTS]
  146. : [Number(event.projectID)],
  147. version: 2,
  148. ...dateSelection,
  149. });
  150. return eventView.getResultsViewUrlTarget(organization.slug);
  151. }