dynamicSampling.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  4. import {Button} from 'sentry/components/button';
  5. import Confirm from 'sentry/components/confirm';
  6. import FieldGroup from 'sentry/components/forms/fieldGroup';
  7. import Panel from 'sentry/components/panels/panel';
  8. import PanelBody from 'sentry/components/panels/panelBody';
  9. import PanelHeader from 'sentry/components/panels/panelHeader';
  10. import {t} from 'sentry/locale';
  11. import {space} from 'sentry/styles/space';
  12. import {useMutation} from 'sentry/utils/queryClient';
  13. import useApi from 'sentry/utils/useApi';
  14. import useOrganization from 'sentry/utils/useOrganization';
  15. import {dynamicSamplingForm} from 'sentry/views/settings/dynamicSampling/dynamicSamplingForm';
  16. import {TargetSampleRateField} from 'sentry/views/settings/dynamicSampling/targetSampleRateField';
  17. import {useAccess} from 'sentry/views/settings/projectMetrics/access';
  18. const {useFormState, FormProvider} = dynamicSamplingForm;
  19. export function DynamicSampling() {
  20. const api = useApi();
  21. const organization = useOrganization();
  22. const {hasAccess} = useAccess({access: ['org:write']});
  23. const formState = useFormState({
  24. targetSampleRate: ((organization.targetSampleRate ?? 1) * 100)?.toLocaleString(),
  25. samplingMode: 'auto' as const,
  26. });
  27. const modeField = formState.fields.samplingMode;
  28. const endpoint = `/organizations/${organization.slug}/`;
  29. const {mutate: updateOrganization, isPending} = useMutation({
  30. mutationFn: () => {
  31. const {fields} = formState;
  32. return api.requestPromise(endpoint, {
  33. method: 'PUT',
  34. data: {
  35. targetSampleRate: Number(fields.targetSampleRate.value) / 100,
  36. },
  37. });
  38. },
  39. onSuccess: () => {
  40. addSuccessMessage(t('Changes applied.'));
  41. formState.save();
  42. },
  43. onError: () => {
  44. addErrorMessage(t('Unable to save changes. Please try again.'));
  45. },
  46. });
  47. const handleSubmit = () => {
  48. updateOrganization();
  49. };
  50. const handleReset = () => {
  51. formState.reset();
  52. };
  53. return (
  54. <FormProvider formState={formState}>
  55. <form onSubmit={event => event.preventDefault()}>
  56. <Panel>
  57. <PanelHeader>{t('Automatic Sampling')}</PanelHeader>
  58. <PanelBody>
  59. <FieldGroup
  60. label={t('Sampling Mode')}
  61. help={t('Changes the level of detail and configuring sample rates.')}
  62. >
  63. {t('Automatic Balancing')}
  64. </FieldGroup>
  65. {/* TODO(aknaus): move into separate component when we make it interactive */}
  66. <FieldGroup
  67. disabled
  68. label={t('Switch Mode')}
  69. help={t(
  70. 'Take control over the individual sample rates in your projects. This disables automatic adjustments.'
  71. )}
  72. >
  73. <Confirm disabled>
  74. <Button
  75. title={t('This feature is not yet available.')}
  76. css={css`
  77. width: max-content;
  78. `}
  79. >
  80. {modeField.value === 'auto'
  81. ? t('Switch to Manual')
  82. : t('Switch to Auto')}
  83. </Button>
  84. </Confirm>
  85. </FieldGroup>
  86. {modeField.value === 'auto' ? <TargetSampleRateField /> : null}
  87. </PanelBody>
  88. </Panel>
  89. <FormActions>
  90. <Button disabled={!formState.hasChanged || isPending} onClick={handleReset}>
  91. {t('Reset')}
  92. </Button>
  93. <Button
  94. priority="primary"
  95. disabled={
  96. !hasAccess || !formState.isValid || !formState.hasChanged || isPending
  97. }
  98. onClick={handleSubmit}
  99. >
  100. {t('Save changes')}
  101. </Button>
  102. </FormActions>
  103. </form>
  104. </FormProvider>
  105. );
  106. }
  107. const FormActions = styled('div')`
  108. display: grid;
  109. grid-template-columns: repeat(2, max-content);
  110. gap: ${space(1)};
  111. justify-content: flex-end;
  112. `;