useSlowMedianFastSamplesQuery.tsx 4.9 KB

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