metricsProvider.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import {useEffect, useState} from 'react';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import {Client} from 'sentry/api';
  4. import {t} from 'sentry/locale';
  5. import {MetricsMetaCollection, MetricsTagCollection, Organization} from 'sentry/types';
  6. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  7. import useApi from 'sentry/utils/useApi';
  8. import {MetricsContext, MetricsContextValue} from './metricsContext';
  9. function fetchMetricMetas(
  10. api: Client,
  11. organization: Organization,
  12. projects?: number[]
  13. ): Promise<MetricsMetaCollection> {
  14. return api.requestPromise(`/organizations/${organization.slug}/metrics/meta/`, {
  15. query: {
  16. project: projects,
  17. },
  18. });
  19. }
  20. function fetchMetricTags(
  21. api: Client,
  22. organization: Organization,
  23. projects?: number[],
  24. fields?: string[]
  25. ): Promise<MetricsTagCollection> {
  26. return api.requestPromise(`/organizations/${organization.slug}/metrics/tags/`, {
  27. query: {
  28. project: projects,
  29. metrics: fields,
  30. },
  31. });
  32. }
  33. type MetricsProviderProps = {
  34. children: React.ReactNode | ((props: MetricsContextValue) => React.ReactNode);
  35. organization: Organization;
  36. fields?: string[];
  37. projects?: number[];
  38. skipLoad?: boolean;
  39. };
  40. export function MetricsProvider({
  41. children,
  42. fields,
  43. organization,
  44. projects,
  45. skipLoad = false,
  46. }: MetricsProviderProps) {
  47. const api = useApi();
  48. const [state, setState] = useState({metas: {}, tags: {}});
  49. useEffect(() => {
  50. if (skipLoad) {
  51. return undefined;
  52. }
  53. let shouldCancelRequest = false;
  54. fetchMetricMetas(api, organization, projects)
  55. .then(response => {
  56. if (shouldCancelRequest) {
  57. return;
  58. }
  59. setState(oldState => ({...oldState, metas: response}));
  60. })
  61. .catch(e => {
  62. if (shouldCancelRequest) {
  63. return;
  64. }
  65. const errorResponse = e?.responseJSON ?? t('Unable to fetch metric metas');
  66. addErrorMessage(errorResponse);
  67. handleXhrErrorResponse(errorResponse)(e);
  68. });
  69. return () => {
  70. shouldCancelRequest = true;
  71. };
  72. }, [projects, organization.slug, api, skipLoad]);
  73. useEffect(() => {
  74. if (skipLoad) {
  75. return undefined;
  76. }
  77. let shouldCancelRequest = false;
  78. fetchMetricTags(api, organization, projects, fields)
  79. .then(response => {
  80. if (shouldCancelRequest) {
  81. return;
  82. }
  83. setState(oldState => ({...oldState, tags: response}));
  84. })
  85. .catch(e => {
  86. if (shouldCancelRequest) {
  87. return;
  88. }
  89. const errorResponse = e?.responseJSON ?? t('Unable to fetch metric tags');
  90. addErrorMessage(errorResponse);
  91. handleXhrErrorResponse(errorResponse)(e);
  92. });
  93. return () => {
  94. shouldCancelRequest = true;
  95. };
  96. }, [projects, organization.slug, api, fields, skipLoad]);
  97. return (
  98. <MetricsContext.Provider value={state}>
  99. {typeof children === 'function' ? children(state) : children}
  100. </MetricsContext.Provider>
  101. );
  102. }