useTraceTimelineEvents.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {useMemo} from 'react';
  2. import type {Event} from 'sentry/types';
  3. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  4. import {getTraceTimeRangeFromEvent} from 'sentry/utils/performance/quickTrace/utils';
  5. import {useApiQuery} from 'sentry/utils/queryClient';
  6. import useOrganization from 'sentry/utils/useOrganization';
  7. interface BaseEvent {
  8. id: string;
  9. 'issue.id': number;
  10. project: string;
  11. 'project.name': string;
  12. timestamp: string;
  13. title: string;
  14. transaction: string;
  15. }
  16. interface TimelineDiscoverEvent extends BaseEvent {}
  17. interface TimelineIssuePlatformEvent extends BaseEvent {
  18. 'event.type': string;
  19. 'stack.function': string[];
  20. }
  21. export type TimelineEvent = TimelineDiscoverEvent | TimelineIssuePlatformEvent;
  22. export interface TraceEventResponse {
  23. data: TimelineEvent[];
  24. meta: unknown;
  25. }
  26. interface UseTraceTimelineEventsOptions {
  27. event: Event;
  28. }
  29. export function useTraceTimelineEvents(
  30. {event}: UseTraceTimelineEventsOptions,
  31. isEnabled: boolean = true
  32. ): {
  33. endTimestamp: number;
  34. isError: boolean;
  35. isLoading: boolean;
  36. startTimestamp: number;
  37. traceEvents: TimelineEvent[];
  38. } {
  39. const organization = useOrganization();
  40. const {start, end} = getTraceTimeRangeFromEvent(event);
  41. const traceId = event.contexts?.trace?.trace_id ?? '';
  42. const enabled = !!traceId && isEnabled;
  43. const {
  44. data: issuePlatformData,
  45. isLoading: isLoadingIssuePlatform,
  46. isError: isErrorIssuePlatform,
  47. } = useApiQuery<TraceEventResponse>(
  48. [
  49. `/organizations/${organization.slug}/events/`,
  50. {
  51. query: {
  52. // Get performance issues
  53. dataset: DiscoverDatasets.ISSUE_PLATFORM,
  54. field: ['title', 'project', 'timestamp', 'issue.id', 'transaction'],
  55. per_page: 100,
  56. query: `trace:${traceId}`,
  57. referrer: 'api.issues.issue_events',
  58. sort: '-timestamp',
  59. start,
  60. end,
  61. },
  62. },
  63. ],
  64. {staleTime: Infinity, retry: false, enabled}
  65. );
  66. const {
  67. data: discoverData,
  68. isLoading: isLoadingDiscover,
  69. isError: isErrorDiscover,
  70. } = useApiQuery<{
  71. data: TimelineEvent[];
  72. meta: unknown;
  73. }>(
  74. [
  75. `/organizations/${organization.slug}/events/`,
  76. {
  77. query: {
  78. // Other events
  79. dataset: DiscoverDatasets.DISCOVER,
  80. field: [
  81. 'title',
  82. 'project',
  83. 'timestamp',
  84. 'issue.id',
  85. 'transaction',
  86. 'event.type',
  87. 'stack.function',
  88. ],
  89. per_page: 100,
  90. query: `trace:${traceId}`,
  91. referrer: 'api.issues.issue_events',
  92. sort: '-timestamp',
  93. start,
  94. end,
  95. },
  96. },
  97. ],
  98. {staleTime: Infinity, retry: false, enabled}
  99. );
  100. const eventData = useMemo(() => {
  101. if (
  102. isLoadingIssuePlatform ||
  103. isLoadingDiscover ||
  104. isErrorIssuePlatform ||
  105. isErrorDiscover
  106. ) {
  107. return {
  108. data: [],
  109. startTimestamp: 0,
  110. endTimestamp: 0,
  111. };
  112. }
  113. // Events is unsorted since they're grouped by date later
  114. const events = [...issuePlatformData.data, ...discoverData.data];
  115. // The current event might be missing when there is a large number of issues
  116. const hasCurrentEvent = events.some(e => e.id === event.id);
  117. if (!hasCurrentEvent) {
  118. events.push({
  119. id: event.id,
  120. 'issue.id': Number(event.groupID),
  121. project: event.projectID,
  122. // The project name for current event is not used
  123. 'project.name': '',
  124. timestamp: event.dateCreated!,
  125. title: event.title,
  126. transaction: '',
  127. });
  128. }
  129. const timestamps = events.map(e => new Date(e.timestamp).getTime());
  130. const startTimestamp = Math.min(...timestamps);
  131. const endTimestamp = Math.max(...timestamps);
  132. return {
  133. data: events,
  134. startTimestamp,
  135. endTimestamp,
  136. };
  137. }, [
  138. event,
  139. issuePlatformData,
  140. discoverData,
  141. isLoadingIssuePlatform,
  142. isLoadingDiscover,
  143. isErrorIssuePlatform,
  144. isErrorDiscover,
  145. ]);
  146. return {
  147. traceEvents: eventData.data,
  148. startTimestamp: eventData.startTimestamp,
  149. endTimestamp: eventData.endTimestamp,
  150. isLoading: isLoadingIssuePlatform || isLoadingDiscover,
  151. isError: isErrorIssuePlatform || isErrorDiscover,
  152. };
  153. }