useDiscover.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import type {PageFilters} from 'sentry/types/core';
  2. import EventView from 'sentry/utils/discover/eventView';
  3. import type {Sort} from 'sentry/utils/discover/fields';
  4. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  5. import type {MutableSearch} from 'sentry/utils/tokenizeSearch';
  6. import usePageFilters from 'sentry/utils/usePageFilters';
  7. import {useWrappedDiscoverQuery} from 'sentry/views/insights/common/queries/useSpansQuery';
  8. import type {
  9. EAPSpanProperty,
  10. EAPSpanResponse,
  11. MetricsProperty,
  12. MetricsResponse,
  13. SpanIndexedProperty,
  14. SpanIndexedResponse,
  15. SpanMetricsProperty,
  16. SpanMetricsResponse,
  17. } from 'sentry/views/insights/types';
  18. interface UseMetricsOptions<Fields> {
  19. cursor?: string;
  20. enabled?: boolean;
  21. fields?: Fields;
  22. limit?: number;
  23. noPagination?: boolean;
  24. pageFilters?: PageFilters;
  25. search?: MutableSearch | string; // TODO - ideally this probably would be only `Mutable Search`, but it doesn't handle some situations well
  26. sorts?: Sort[];
  27. }
  28. export const useSpansIndexed = <Fields extends SpanIndexedProperty[]>(
  29. options: UseMetricsOptions<Fields> = {},
  30. referrer: string
  31. ) => {
  32. return useDiscover<Fields, SpanIndexedResponse>(
  33. options,
  34. DiscoverDatasets.SPANS_INDEXED,
  35. referrer
  36. );
  37. };
  38. export const useEAPSpans = <Fields extends EAPSpanProperty[]>(
  39. options: UseMetricsOptions<Fields> = {},
  40. referrer: string
  41. ) => {
  42. return useDiscover<Fields, EAPSpanResponse>(
  43. options,
  44. DiscoverDatasets.SPANS_EAP,
  45. referrer
  46. );
  47. };
  48. export const useSpanMetrics = <Fields extends SpanMetricsProperty[]>(
  49. options: UseMetricsOptions<Fields> = {},
  50. referrer: string
  51. ) => {
  52. return useDiscover<Fields, SpanMetricsResponse>(
  53. options,
  54. DiscoverDatasets.SPANS_METRICS,
  55. referrer
  56. );
  57. };
  58. export const useMetrics = <Fields extends MetricsProperty[]>(
  59. options: UseMetricsOptions<Fields> = {},
  60. referrer: string
  61. ) => {
  62. return useDiscover<Fields, MetricsResponse>(
  63. options,
  64. DiscoverDatasets.METRICS,
  65. referrer
  66. );
  67. };
  68. const useDiscover = <T extends Extract<keyof ResponseType, string>[], ResponseType>(
  69. options: UseMetricsOptions<T> = {},
  70. dataset: DiscoverDatasets,
  71. referrer: string
  72. ) => {
  73. const {
  74. fields = [],
  75. search = undefined,
  76. sorts = [],
  77. limit,
  78. cursor,
  79. pageFilters: pageFiltersFromOptions,
  80. noPagination,
  81. } = options;
  82. const pageFilters = usePageFilters();
  83. const eventView = getEventView(
  84. search,
  85. fields,
  86. sorts,
  87. pageFiltersFromOptions ?? pageFilters.selection,
  88. dataset
  89. );
  90. const result = useWrappedDiscoverQuery({
  91. eventView,
  92. initialData: [],
  93. limit,
  94. enabled: options.enabled,
  95. referrer,
  96. cursor,
  97. noPagination,
  98. });
  99. // This type is a little awkward but it explicitly states that the response could be empty. This doesn't enable unchecked access errors, but it at least indicates that it's possible that there's no data
  100. const data = (result?.data ?? []) as Pick<ResponseType, T[number]>[];
  101. return {
  102. ...result,
  103. data,
  104. isEnabled: options.enabled,
  105. };
  106. };
  107. function getEventView(
  108. search: MutableSearch | string | undefined,
  109. fields: string[] = [],
  110. sorts: Sort[] = [],
  111. pageFilters: PageFilters,
  112. dataset: DiscoverDatasets
  113. ) {
  114. const query = typeof search === 'string' ? search : search?.formatString() ?? '';
  115. const eventView = EventView.fromNewQueryWithPageFilters(
  116. {
  117. name: '',
  118. query,
  119. fields,
  120. dataset,
  121. version: 2,
  122. },
  123. pageFilters
  124. );
  125. if (sorts.length > 0) {
  126. eventView.sorts = sorts;
  127. }
  128. return eventView;
  129. }