useSlowMedianFastSamplesQuery.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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: 'transaction.duration',
  30. kind: 'field',
  31. },
  32. {
  33. field: 'profile_id',
  34. kind: 'field',
  35. },
  36. {
  37. field: 'timestamp',
  38. kind: 'field',
  39. },
  40. {
  41. field: 'spans.browser',
  42. kind: 'field',
  43. },
  44. {
  45. field: 'spans.db',
  46. kind: 'field',
  47. },
  48. {
  49. field: 'spans.http',
  50. kind: 'field',
  51. },
  52. {
  53. field: 'spans.resource',
  54. kind: 'field',
  55. },
  56. {
  57. field: 'spans.ui',
  58. kind: 'field',
  59. },
  60. ];
  61. const eventViewAggregates = eventView
  62. .clone()
  63. .withColumns([
  64. {kind: 'function', function: ['avg', 'transaction.duration', undefined, undefined]},
  65. ]);
  66. const {isLoading: isLoadingAgg, data: aggregatesData} = useDiscoverQuery({
  67. eventView: eventViewAggregates,
  68. referrer: 'starfish-transaction-summary-sample-events',
  69. location,
  70. orgSlug: organization.slug,
  71. options: {
  72. refetchOnWindowFocus: false,
  73. enabled: graphMax !== undefined,
  74. },
  75. });
  76. const avg = aggregatesData
  77. ? aggregatesData.data[0]['avg(transaction.duration)']
  78. : undefined;
  79. const upperThird = graphMax ? max([graphMax * (2 / 3), avg]) : undefined;
  80. const lowerThird = graphMax ? graphMax * (1 / 3) : undefined;
  81. const slowestSamplesEventView = eventView
  82. .clone()
  83. .withColumns(commonColumns)
  84. .withSorts([
  85. {
  86. field: 'id',
  87. kind: 'desc',
  88. },
  89. ]);
  90. slowestSamplesEventView.additionalConditions = new MutableSearch(
  91. `transaction.duration:<${graphMax} transaction.duration:>${upperThird}`
  92. );
  93. const {isLoading: isLoadingSlowest, data: slowestSamplesData} = useDiscoverQuery({
  94. eventView: slowestSamplesEventView,
  95. referrer: 'starfish-transaction-summary-sample-events',
  96. location,
  97. orgSlug: organization.slug,
  98. limit: LIMIT_PER_POPULATION,
  99. options: {
  100. refetchOnWindowFocus: false,
  101. enabled: graphMax !== undefined && avg !== undefined,
  102. },
  103. });
  104. const medianSamplesEventView = eventView
  105. .clone()
  106. .withColumns(commonColumns)
  107. .withSorts([
  108. {
  109. field: 'transaction.duration',
  110. kind: 'desc',
  111. },
  112. ]);
  113. medianSamplesEventView.additionalConditions = new MutableSearch(
  114. `transaction.duration:<=${upperThird} transaction.duration:>${lowerThird}`
  115. );
  116. const {isLoading: isLoadingMedian, data: medianSamplesData} = useDiscoverQuery({
  117. eventView: medianSamplesEventView,
  118. referrer: 'starfish-transaction-summary-sample-events',
  119. location,
  120. orgSlug: organization.slug,
  121. limit: LIMIT_PER_POPULATION,
  122. options: {
  123. refetchOnWindowFocus: false,
  124. enabled: graphMax !== undefined && avg !== undefined,
  125. },
  126. });
  127. const fastestSamplesEventView = eventView
  128. .clone()
  129. .withColumns(commonColumns)
  130. .withSorts([
  131. {
  132. field: 'transaction.duration',
  133. kind: 'asc',
  134. },
  135. ]);
  136. fastestSamplesEventView.additionalConditions = new MutableSearch(
  137. `transaction.duration:<=${lowerThird}`
  138. );
  139. const {isLoading: isLoadingFastest, data: fastestSamplesData} = useDiscoverQuery({
  140. eventView: fastestSamplesEventView,
  141. referrer: 'starfish-transaction-summary-sample-events',
  142. location,
  143. orgSlug: organization.slug,
  144. limit: LIMIT_PER_POPULATION,
  145. options: {
  146. refetchOnWindowFocus: false,
  147. enabled: graphMax !== undefined,
  148. },
  149. });
  150. if (isLoadingAgg || isLoadingSlowest || isLoadingMedian || isLoadingFastest) {
  151. return {isLoading: true, data: []};
  152. }
  153. const combinedData = [
  154. ...(slowestSamplesData?.data ?? []),
  155. ...(medianSamplesData?.data ?? []),
  156. ...(fastestSamplesData?.data ?? []),
  157. ];
  158. return {
  159. isLoading: false,
  160. data: combinedData as DataRow[],
  161. aggregatesData: aggregatesData?.data[0] ?? [],
  162. };
  163. }