useSpanSamples.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // TODO: This is a _more general_ version of `useSpanSamples` from `/starfish/queries`. That hook should rely on this one _or_ they should be consolidated.
  2. import {defined} from 'sentry/utils';
  3. import {useApiQuery} from 'sentry/utils/queryClient';
  4. import type {MutableSearch} from 'sentry/utils/tokenizeSearch';
  5. import useOrganization from 'sentry/utils/useOrganization';
  6. import usePageFilters from 'sentry/utils/usePageFilters';
  7. import {getDateConditions} from 'sentry/views/insights/common/utils/getDateConditions';
  8. import type {
  9. SpanIndexedField,
  10. SpanIndexedProperty,
  11. SpanIndexedResponse,
  12. } from 'sentry/views/insights/types';
  13. interface UseSpanSamplesOptions<Fields> {
  14. enabled?: boolean;
  15. fields?: Fields;
  16. max?: number;
  17. min?: number;
  18. referrer?: string;
  19. search?: MutableSearch;
  20. }
  21. export const useSpanSamples = <Fields extends SpanIndexedProperty[]>(
  22. options: UseSpanSamplesOptions<Fields> = {}
  23. ) => {
  24. const {
  25. fields = [],
  26. search = undefined,
  27. referrer,
  28. enabled,
  29. min = undefined,
  30. max = undefined,
  31. } = options;
  32. const {selection} = usePageFilters();
  33. const organization = useOrganization();
  34. if (defined(min) && min < 0) {
  35. throw new Error('Minimum must be greater than 0');
  36. }
  37. if (defined(min) && defined(max) && min >= max) {
  38. throw new Error('Maximum must be higher than minimum');
  39. }
  40. const dateConditions = getDateConditions(selection);
  41. const result = useApiQuery<{
  42. data:
  43. | Pick<
  44. SpanIndexedResponse,
  45. | Fields[number]
  46. // These fields are returned by default
  47. | SpanIndexedField.PROJECT
  48. | SpanIndexedField.TRANSACTION_ID
  49. | SpanIndexedField.TIMESTAMP
  50. | SpanIndexedField.ID
  51. | SpanIndexedField.PROFILE_ID
  52. | SpanIndexedField.SPAN_SELF_TIME
  53. >[]
  54. // 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
  55. // eslint-disable-next-line @typescript-eslint/no-restricted-types
  56. | [];
  57. }>(
  58. [
  59. `/api/0/organizations/${organization.slug}/spans-samples/`,
  60. {
  61. query: {
  62. query: search?.formatString(),
  63. project: selection.projects,
  64. ...dateConditions,
  65. ...{utc: selection.datetime.utc},
  66. lowerBound: min,
  67. firstBound: max && max * (1 / 3),
  68. secondBound: max && max * (2 / 3),
  69. upperBound: max,
  70. additionalFields: fields,
  71. referrer,
  72. },
  73. },
  74. ],
  75. {
  76. enabled,
  77. staleTime: Infinity,
  78. retry: false,
  79. }
  80. );
  81. return {
  82. ...result,
  83. data: result.data?.data ?? [],
  84. };
  85. };