useSlowMedianFastSamplesQuery.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import max from 'lodash/max';
  2. import {useDiscoverQuery} from 'sentry/utils/discover/discoverQuery';
  3. import type EventView from 'sentry/utils/discover/eventView';
  4. import type {QueryFieldValue} from 'sentry/utils/discover/fields';
  5. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  6. import {useLocation} from 'sentry/utils/useLocation';
  7. import useOrganization from 'sentry/utils/useOrganization';
  8. type DataRow = {
  9. 'http.status_code': number;
  10. id: string;
  11. profile_id: string;
  12. project: string;
  13. 'spans.browser': number;
  14. 'spans.db': number;
  15. 'spans.http': number;
  16. 'spans.resource': number;
  17. 'spans.ui': number;
  18. timestamp: string;
  19. trace: string;
  20. 'transaction.duration': number;
  21. 'transaction.status': string;
  22. };
  23. const LIMIT_PER_POPULATION = 2;
  24. /**
  25. * This hook will fetch transaction events from 3 different types of populations and combine them in one set, then return them:
  26. *
  27. * - Slowest Events
  28. * - Median / Baseline Events
  29. * - Fastest Events
  30. *
  31. * It assumes that you are passing an eventView object with a query scoped to a specific transaction
  32. *
  33. * @param eventView An eventView containing query information, such as the transaction and other filters
  34. */
  35. export default function useSlowMedianFastSamplesQuery(
  36. eventView: EventView,
  37. graphMax?: number
  38. ) {
  39. const location = useLocation();
  40. const organization = useOrganization();
  41. const commonColumns: QueryFieldValue[] = [
  42. {
  43. field: 'trace',
  44. kind: 'field',
  45. },
  46. {
  47. field: 'transaction.duration',
  48. kind: 'field',
  49. },
  50. {
  51. field: 'profile_id',
  52. kind: 'field',
  53. },
  54. {
  55. field: 'timestamp',
  56. kind: 'field',
  57. },
  58. {
  59. field: 'spans.browser',
  60. kind: 'field',
  61. },
  62. {
  63. field: 'spans.db',
  64. kind: 'field',
  65. },
  66. {
  67. field: 'spans.http',
  68. kind: 'field',
  69. },
  70. {
  71. field: 'spans.resource',
  72. kind: 'field',
  73. },
  74. {
  75. field: 'spans.ui',
  76. kind: 'field',
  77. },
  78. ];
  79. const eventViewAggregates = eventView
  80. .clone()
  81. .withColumns([
  82. {kind: 'function', function: ['avg', 'transaction.duration', undefined, undefined]},
  83. ]);
  84. const {isLoading: isLoadingAgg, data: aggregatesData} = useDiscoverQuery({
  85. eventView: eventViewAggregates,
  86. referrer: 'starfish-transaction-summary-sample-events',
  87. location,
  88. orgSlug: organization.slug,
  89. options: {
  90. refetchOnWindowFocus: false,
  91. enabled: graphMax !== undefined,
  92. },
  93. });
  94. const avg = aggregatesData
  95. ? aggregatesData.data[0]['avg(transaction.duration)']
  96. : undefined;
  97. const upperThird = graphMax ? max([graphMax * (2 / 3), avg]) : undefined;
  98. const lowerThird = graphMax ? graphMax * (1 / 3) : undefined;
  99. const slowestSamplesEventView = eventView
  100. .clone()
  101. .withColumns(commonColumns)
  102. .withSorts([
  103. {
  104. field: 'id',
  105. kind: 'desc',
  106. },
  107. ]);
  108. slowestSamplesEventView.additionalConditions = new MutableSearch(
  109. `transaction.duration:<${graphMax} transaction.duration:>${upperThird}`
  110. );
  111. const {isLoading: isLoadingSlowest, data: slowestSamplesData} = useDiscoverQuery({
  112. eventView: slowestSamplesEventView,
  113. referrer: 'starfish-transaction-summary-sample-events',
  114. location,
  115. orgSlug: organization.slug,
  116. limit: LIMIT_PER_POPULATION,
  117. options: {
  118. refetchOnWindowFocus: false,
  119. enabled: graphMax !== undefined && avg !== undefined,
  120. },
  121. });
  122. const medianSamplesEventView = eventView
  123. .clone()
  124. .withColumns(commonColumns)
  125. .withSorts([
  126. {
  127. field: 'transaction.duration',
  128. kind: 'desc',
  129. },
  130. ]);
  131. medianSamplesEventView.additionalConditions = new MutableSearch(
  132. `transaction.duration:<=${upperThird} transaction.duration:>${lowerThird}`
  133. );
  134. const {isLoading: isLoadingMedian, data: medianSamplesData} = useDiscoverQuery({
  135. eventView: medianSamplesEventView,
  136. referrer: 'starfish-transaction-summary-sample-events',
  137. location,
  138. orgSlug: organization.slug,
  139. limit: LIMIT_PER_POPULATION,
  140. options: {
  141. refetchOnWindowFocus: false,
  142. enabled: graphMax !== undefined && avg !== undefined,
  143. },
  144. });
  145. const fastestSamplesEventView = eventView
  146. .clone()
  147. .withColumns(commonColumns)
  148. .withSorts([
  149. {
  150. field: 'transaction.duration',
  151. kind: 'asc',
  152. },
  153. ]);
  154. fastestSamplesEventView.additionalConditions = new MutableSearch(
  155. `transaction.duration:<=${lowerThird}`
  156. );
  157. const {isLoading: isLoadingFastest, data: fastestSamplesData} = useDiscoverQuery({
  158. eventView: fastestSamplesEventView,
  159. referrer: 'starfish-transaction-summary-sample-events',
  160. location,
  161. orgSlug: organization.slug,
  162. limit: LIMIT_PER_POPULATION,
  163. options: {
  164. refetchOnWindowFocus: false,
  165. enabled: graphMax !== undefined,
  166. },
  167. });
  168. if (isLoadingAgg || isLoadingSlowest || isLoadingMedian || isLoadingFastest) {
  169. return {isLoading: true, data: []};
  170. }
  171. const combinedData = [
  172. ...(slowestSamplesData?.data ?? []),
  173. ...(medianSamplesData?.data ?? []),
  174. ...(fastestSamplesData?.data ?? []),
  175. ];
  176. return {
  177. isLoading: false,
  178. data: combinedData as DataRow[],
  179. aggregatesData: aggregatesData?.data[0] ?? [],
  180. };
  181. }