utils.tsx 5.5 KB

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