useSpanMetrics.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import type {PageFilters} from 'sentry/types';
  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 {MutableSearch} from 'sentry/utils/tokenizeSearch';
  6. import usePageFilters from 'sentry/utils/usePageFilters';
  7. import type {
  8. MetricsProperty,
  9. MetricsResponse,
  10. SpanMetricsQueryFilters,
  11. } from 'sentry/views/starfish/types';
  12. import {useWrappedDiscoverQuery} from 'sentry/views/starfish/utils/useSpansQuery';
  13. interface UseSpanMetricsOptions<Fields> {
  14. cursor?: string;
  15. enabled?: boolean;
  16. fields?: Fields;
  17. filters?: SpanMetricsQueryFilters;
  18. limit?: number;
  19. referrer?: string;
  20. sorts?: Sort[];
  21. }
  22. export const useSpanMetrics = <Fields extends MetricsProperty[]>(
  23. options: UseSpanMetricsOptions<Fields> = {}
  24. ) => {
  25. const {fields = [], filters = {}, sorts = [], limit, cursor, referrer} = options;
  26. const pageFilters = usePageFilters();
  27. const eventView = getEventView(filters, fields, sorts, pageFilters.selection);
  28. // TODO: Checking that every filter has a value might not be a good choice, since this API is not convenient. Instead, it's probably fine to omit keys with blank values
  29. const enabled =
  30. options.enabled && Object.values(filters).every(value => Boolean(value));
  31. const result = useWrappedDiscoverQuery({
  32. eventView,
  33. initialData: [],
  34. limit,
  35. enabled,
  36. referrer,
  37. cursor,
  38. });
  39. // 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
  40. // eslint-disable-next-line @typescript-eslint/ban-types
  41. const data = (result?.data ?? []) as Pick<MetricsResponse, Fields[number]>[] | [];
  42. return {
  43. ...result,
  44. data,
  45. isEnabled: enabled,
  46. };
  47. };
  48. function getEventView(
  49. filters: SpanMetricsQueryFilters = {},
  50. fields: string[] = [],
  51. sorts: Sort[] = [],
  52. pageFilters: PageFilters
  53. ) {
  54. const query = MutableSearch.fromQueryObject(filters);
  55. const eventView = EventView.fromNewQueryWithPageFilters(
  56. {
  57. name: '',
  58. query: query.formatString(),
  59. fields,
  60. dataset: DiscoverDatasets.SPANS_METRICS,
  61. version: 2,
  62. },
  63. pageFilters
  64. );
  65. if (sorts.length > 0) {
  66. eventView.sorts = sorts;
  67. }
  68. return eventView;
  69. }