customMeasurementsProvider.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import {useEffect, useState} from 'react';
  2. import {Query} from 'history';
  3. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  4. import {Client} from 'sentry/api';
  5. import {getFieldTypeFromUnit} from 'sentry/components/events/eventCustomPerformanceMetrics';
  6. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  7. import {t} from 'sentry/locale';
  8. import {Organization, PageFilters} from 'sentry/types';
  9. import {CustomMeasurementCollection} from 'sentry/utils/customMeasurements/customMeasurements';
  10. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  11. import useApi from 'sentry/utils/useApi';
  12. import {
  13. CustomMeasurementsContext,
  14. CustomMeasurementsContextValue,
  15. } from './customMeasurementsContext';
  16. type MeasurementsMetaResponse = {
  17. [x: string]: {functions: string[]; unit: string};
  18. };
  19. function fetchCustomMeasurements(
  20. api: Client,
  21. organization: Organization,
  22. selection?: PageFilters
  23. ): Promise<MeasurementsMetaResponse> {
  24. const query: Query = selection?.datetime
  25. ? {...normalizeDateTimeParams(selection.datetime)}
  26. : {};
  27. if (selection?.projects) {
  28. query.project = selection.projects.map(String);
  29. }
  30. return api.requestPromise(`/organizations/${organization.slug}/measurements-meta/`, {
  31. method: 'GET',
  32. query,
  33. });
  34. }
  35. type CustomMeasurementsProviderProps = {
  36. children:
  37. | React.ReactNode
  38. | ((props: CustomMeasurementsContextValue) => React.ReactNode);
  39. organization: Organization;
  40. selection?: PageFilters;
  41. };
  42. export function CustomMeasurementsProvider({
  43. children,
  44. organization,
  45. selection,
  46. }: CustomMeasurementsProviderProps) {
  47. const api = useApi();
  48. const [state, setState] = useState({customMeasurements: {}});
  49. useEffect(() => {
  50. let shouldCancelRequest = false;
  51. if (
  52. organization.features.includes('dashboards-mep') ||
  53. organization.features.includes('mep-rollout-flag')
  54. ) {
  55. fetchCustomMeasurements(api, organization, selection)
  56. .then(response => {
  57. if (shouldCancelRequest) {
  58. return;
  59. }
  60. const newCustomMeasurements = Object.keys(
  61. response
  62. ).reduce<CustomMeasurementCollection>((acc, customMeasurement) => {
  63. acc[customMeasurement] = {
  64. key: customMeasurement,
  65. name: customMeasurement,
  66. functions: response[customMeasurement].functions,
  67. unit: response[customMeasurement].unit,
  68. fieldType: getFieldTypeFromUnit(response[customMeasurement].unit),
  69. };
  70. return acc;
  71. }, {});
  72. setState({customMeasurements: newCustomMeasurements});
  73. })
  74. .catch(e => {
  75. if (shouldCancelRequest) {
  76. return;
  77. }
  78. const errorResponse =
  79. e?.responseJSON ?? t('Unable to fetch custom performance metrics');
  80. addErrorMessage(errorResponse);
  81. handleXhrErrorResponse(errorResponse)(e);
  82. });
  83. }
  84. return () => {
  85. shouldCancelRequest = true;
  86. };
  87. }, [selection, api, organization]);
  88. return (
  89. <CustomMeasurementsContext.Provider value={state}>
  90. {typeof children === 'function' ? children(state) : children}
  91. </CustomMeasurementsContext.Provider>
  92. );
  93. }