useDiscover.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 type {OurLogFieldKey, OurLogsResponseItem} from 'sentry/views/explore/logs/types';
  8. import {useWrappedDiscoverQuery} from 'sentry/views/insights/common/queries/useSpansQuery';
  9. import type {
  10. EAPSpanProperty,
  11. EAPSpanResponse,
  12. MetricsProperty,
  13. MetricsResponse,
  14. SpanIndexedField,
  15. SpanIndexedProperty,
  16. SpanIndexedResponse,
  17. SpanMetricsProperty,
  18. SpanMetricsResponse,
  19. } from 'sentry/views/insights/types';
  20. interface UseMetricsOptions<Fields> {
  21. cursor?: string;
  22. enabled?: boolean;
  23. fields?: Fields;
  24. limit?: number;
  25. noPagination?: boolean;
  26. pageFilters?: PageFilters;
  27. search?: MutableSearch | string; // TODO - ideally this probably would be only `Mutable Search`, but it doesn't handle some situations well
  28. sorts?: Sort[];
  29. }
  30. export const useSpansIndexed = <Fields extends SpanIndexedProperty[]>(
  31. options: UseMetricsOptions<Fields> = {},
  32. referrer: string
  33. ) => {
  34. // Indexed spans dataset always returns an `id`
  35. return useDiscover<Fields | [SpanIndexedField.ID], SpanIndexedResponse>(
  36. options,
  37. DiscoverDatasets.SPANS_INDEXED,
  38. referrer
  39. );
  40. };
  41. export const useOurlogs = <Fields extends OurLogFieldKey[]>(
  42. options: UseMetricsOptions<Fields> = {},
  43. referrer: string
  44. ) => {
  45. const {data, ...rest} = useDiscover<Fields, OurLogsResponseItem>(
  46. options,
  47. DiscoverDatasets.OURLOGS,
  48. referrer
  49. );
  50. const castData = data as OurLogsResponseItem[];
  51. return {...rest, data: castData};
  52. };
  53. export const useEAPSpans = <Fields extends EAPSpanProperty[]>(
  54. options: UseMetricsOptions<Fields> = {},
  55. referrer: string,
  56. useRpc?: boolean
  57. ) => {
  58. return useDiscover<Fields, EAPSpanResponse>(
  59. options,
  60. useRpc ? DiscoverDatasets.SPANS_EAP_RPC : DiscoverDatasets.SPANS_EAP,
  61. referrer
  62. );
  63. };
  64. export const useSpanMetrics = <Fields extends SpanMetricsProperty[]>(
  65. options: UseMetricsOptions<Fields> = {},
  66. referrer: string
  67. ) => {
  68. return useDiscover<Fields, SpanMetricsResponse>(
  69. options,
  70. DiscoverDatasets.SPANS_METRICS,
  71. referrer
  72. );
  73. };
  74. export const useMetrics = <Fields extends MetricsProperty[]>(
  75. options: UseMetricsOptions<Fields> = {},
  76. referrer: string
  77. ) => {
  78. return useDiscover<Fields, MetricsResponse>(
  79. options,
  80. DiscoverDatasets.METRICS,
  81. referrer
  82. );
  83. };
  84. const useDiscover = <T extends Array<Extract<keyof ResponseType, string>>, ResponseType>(
  85. options: UseMetricsOptions<T> = {},
  86. dataset: DiscoverDatasets,
  87. referrer: string
  88. ) => {
  89. const {
  90. fields = [],
  91. search = undefined,
  92. sorts = [],
  93. limit,
  94. cursor,
  95. pageFilters: pageFiltersFromOptions,
  96. noPagination,
  97. } = options;
  98. const pageFilters = usePageFilters();
  99. const eventView = getEventView(
  100. search,
  101. fields,
  102. sorts,
  103. pageFiltersFromOptions ?? pageFilters.selection,
  104. dataset
  105. );
  106. const result = useWrappedDiscoverQuery({
  107. eventView,
  108. initialData: [],
  109. limit,
  110. enabled: options.enabled,
  111. referrer,
  112. cursor,
  113. noPagination,
  114. });
  115. // 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
  116. const data = (result?.data ?? []) as Array<Pick<ResponseType, T[number]>>;
  117. return {
  118. ...result,
  119. data,
  120. isEnabled: options.enabled,
  121. };
  122. };
  123. function getEventView(
  124. search: MutableSearch | string | undefined,
  125. fields: string[] = [],
  126. sorts: Sort[] = [],
  127. pageFilters: PageFilters,
  128. dataset: DiscoverDatasets
  129. ) {
  130. const query = typeof search === 'string' ? search : (search?.formatString() ?? '');
  131. const eventView = EventView.fromNewQueryWithPageFilters(
  132. {
  133. name: '',
  134. query,
  135. fields,
  136. dataset,
  137. version: 2,
  138. },
  139. pageFilters
  140. );
  141. if (sorts.length > 0) {
  142. eventView.sorts = sorts;
  143. }
  144. return eventView;
  145. }