utils.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. isHomepage: location.query.homepage === 'true' || undefined,
  70. });
  71. }
  72. export function generateSingleErrorTarget(
  73. event: TraceError,
  74. organization: OrganizationSummary,
  75. location: Location,
  76. destination: ErrorDestination
  77. ): LocationDescriptor {
  78. switch (destination) {
  79. case 'issue':
  80. return generateIssueEventTarget(event, organization);
  81. case 'discover':
  82. default:
  83. return generateDiscoverEventTarget(event, organization, location);
  84. }
  85. }
  86. export function generateSingleTransactionTarget(
  87. event: EventLite,
  88. organization: OrganizationSummary,
  89. location: Location,
  90. destination: TransactionDestination
  91. ): LocationDescriptor {
  92. switch (destination) {
  93. case 'performance':
  94. return generatePerformanceEventTarget(event, organization, location);
  95. case 'discover':
  96. default:
  97. return generateDiscoverEventTarget(event, organization, location);
  98. }
  99. }
  100. export function generateMultiTransactionsTarget(
  101. currentEvent: Event,
  102. events: EventLite[],
  103. organization: OrganizationSummary,
  104. groupType: 'Ancestor' | 'Children' | 'Descendant'
  105. ): LocationDescriptor {
  106. const queryResults = new MutableSearch([]);
  107. const eventIds = events.map(child => child.event_id);
  108. for (let i = 0; i < eventIds.length; i++) {
  109. queryResults.addOp(i === 0 ? '(' : 'OR');
  110. queryResults.addFreeText(`id:${eventIds[i]}`);
  111. if (i === eventIds.length - 1) {
  112. queryResults.addOp(')');
  113. }
  114. }
  115. const {start, end} = getTraceTimeRangeFromEvent(currentEvent);
  116. const traceEventView = EventView.fromSavedQuery({
  117. id: undefined,
  118. name: `${groupType} Transactions of Event ID ${currentEvent.id}`,
  119. fields: ['transaction', 'project', 'trace.span', 'transaction.duration', 'timestamp'],
  120. orderby: '-timestamp',
  121. query: queryResults.formatString(),
  122. projects: [...new Set(events.map(child => child.project_id))],
  123. version: 2,
  124. start,
  125. end,
  126. });
  127. return traceEventView.getResultsViewUrlTarget(organization.slug);
  128. }
  129. export function generateTraceTarget(
  130. event: Event,
  131. organization: OrganizationSummary
  132. ): LocationDescriptor {
  133. const traceId = event.contexts?.trace?.trace_id ?? '';
  134. const dateSelection = normalizeDateTimeParams(getTraceTimeRangeFromEvent(event));
  135. if (organization.features.includes('performance-view')) {
  136. // TODO(txiao): Should this persist the current query when going to trace view?
  137. return getTraceDetailsUrl(organization, traceId, dateSelection, {});
  138. }
  139. const eventView = EventView.fromSavedQuery({
  140. id: undefined,
  141. name: `Events with Trace ID ${traceId}`,
  142. fields: ['title', 'event.type', 'project', 'trace.span', 'timestamp'],
  143. orderby: '-timestamp',
  144. query: `trace:${traceId}`,
  145. projects: organization.features.includes('global-views')
  146. ? [ALL_ACCESS_PROJECTS]
  147. : [Number(event.projectID)],
  148. version: 2,
  149. ...dateSelection,
  150. });
  151. return eventView.getResultsViewUrlTarget(organization.slug);
  152. }