useFunctions.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {useEffect, useState} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import {Client} from 'sentry/api';
  4. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  5. import {t} from 'sentry/locale';
  6. import {Organization, PageFilters, Project, RequestState} from 'sentry/types';
  7. import {FunctionCall, SuspectFunction} from 'sentry/types/profiling/core';
  8. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  9. import useApi from 'sentry/utils/useApi';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. type FunctionsResultV1 = {
  12. functions: FunctionCall[];
  13. version: 1;
  14. };
  15. type FunctionsResultV2 = {
  16. functions: SuspectFunction[];
  17. pageLinks: string | null;
  18. version: 2;
  19. };
  20. type FunctionsResult = FunctionsResultV1 | FunctionsResultV2;
  21. export function isFunctionsResultV1(
  22. result: FunctionsResult
  23. ): result is FunctionsResultV1 {
  24. return result.version === 1;
  25. }
  26. export function isFunctionsResultV2(
  27. result: FunctionsResult
  28. ): result is FunctionsResultV2 {
  29. return result.version === 2;
  30. }
  31. interface UseFunctionsOptions {
  32. project: Project;
  33. query: string;
  34. sort: string;
  35. transaction: string;
  36. cursor?: string;
  37. selection?: PageFilters;
  38. }
  39. function useFunctions({
  40. project,
  41. query,
  42. transaction,
  43. sort,
  44. cursor,
  45. selection,
  46. }: UseFunctionsOptions): RequestState<FunctionsResult> {
  47. const api = useApi();
  48. const organization = useOrganization();
  49. const [requestState, setRequestState] = useState<RequestState<FunctionsResult>>({
  50. type: 'initial',
  51. });
  52. useEffect(() => {
  53. if (selection === undefined) {
  54. return undefined;
  55. }
  56. setRequestState({type: 'loading'});
  57. fetchFunctions(api, organization, {
  58. projectSlug: project.slug,
  59. query,
  60. selection,
  61. sort,
  62. transaction,
  63. cursor,
  64. })
  65. .then(([functions, , response]) => {
  66. const isLegacy =
  67. functions.functions.length && functions.functions[0].hasOwnProperty('symbol');
  68. if (isLegacy) {
  69. setRequestState({
  70. type: 'resolved',
  71. data: {
  72. functions: functions.functions ?? [],
  73. version: 1,
  74. },
  75. });
  76. } else {
  77. setRequestState({
  78. type: 'resolved',
  79. data: {
  80. functions: functions.functions ?? [],
  81. pageLinks: response?.getResponseHeader('Link') ?? null,
  82. version: 2,
  83. },
  84. });
  85. }
  86. })
  87. .catch(err => {
  88. setRequestState({type: 'errored', error: t('Error: Unable to load functions')});
  89. Sentry.captureException(err);
  90. });
  91. return () => api.clear();
  92. }, [api, cursor, organization, project.slug, query, selection, sort, transaction]);
  93. return requestState;
  94. }
  95. function fetchFunctions(
  96. api: Client,
  97. organization: Organization,
  98. {
  99. cursor,
  100. projectSlug,
  101. query,
  102. selection,
  103. sort,
  104. transaction,
  105. }: {
  106. cursor: string | undefined;
  107. projectSlug: Project['slug'];
  108. query: string;
  109. selection: PageFilters;
  110. sort: string;
  111. transaction: string;
  112. }
  113. ) {
  114. const conditions = new MutableSearch(query);
  115. conditions.setFilterValues('transaction_name', [transaction]);
  116. return api.requestPromise(
  117. `/projects/${organization.slug}/${projectSlug}/profiling/functions/`,
  118. {
  119. method: 'GET',
  120. includeAllArgs: true,
  121. query: {
  122. cursor,
  123. environment: selection.environments,
  124. ...normalizeDateTimeParams(selection.datetime),
  125. query: conditions.formatString(),
  126. sort,
  127. },
  128. }
  129. );
  130. }
  131. export {useFunctions};