samplingModeField.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {
  4. addErrorMessage,
  5. addLoadingMessage,
  6. addSuccessMessage,
  7. } from 'sentry/actionCreators/indicator';
  8. import {openConfirmModal} from 'sentry/components/confirm';
  9. import FieldGroup from 'sentry/components/forms/fieldGroup';
  10. import ExternalLink from 'sentry/components/links/externalLink';
  11. import QuestionTooltip from 'sentry/components/questionTooltip';
  12. import {SegmentedControl} from 'sentry/components/segmentedControl';
  13. import {t, tct} from 'sentry/locale';
  14. import {space} from 'sentry/styles/space';
  15. import useOrganization from 'sentry/utils/useOrganization';
  16. import {useUpdateOrganization} from 'sentry/views/settings/dynamicSampling/utils/useUpdateOrganization';
  17. import {useAccess} from 'sentry/views/settings/projectMetrics/access';
  18. const switchToManualMessage = tct(
  19. 'Switching to manual mode disables automatic adjustments. After the switch, you can configure individual sample rates for each project. Dynamic sampling priorities continue to apply within the projects. [link:Learn more]',
  20. {
  21. link: (
  22. <ExternalLink href="https://docs.sentry.io/product/performance/retention-priorities/" />
  23. ),
  24. }
  25. );
  26. const switchToAutoMessage = tct(
  27. 'Switching to automatic mode enables continuous adjustments for your projects based on a global target sample rate. Sentry boosts the sample rates of small projects and ensures equal visibility. [link:Learn more]',
  28. {
  29. link: (
  30. <ExternalLink href="https://docs.sentry.io/product/performance/retention-priorities/" />
  31. ),
  32. }
  33. );
  34. export function SamplingModeField() {
  35. const {samplingMode} = useOrganization();
  36. const {hasAccess} = useAccess({access: ['org:write']});
  37. const {mutate: updateOrganization, isPending} = useUpdateOrganization({
  38. onMutate: () => {
  39. addLoadingMessage(t('Switching sampling mode...'));
  40. },
  41. onSuccess: () => {
  42. addSuccessMessage(t('Changes applied.'));
  43. },
  44. onError: () => {
  45. addErrorMessage(t('Unable to save changes. Please try again.'));
  46. },
  47. });
  48. const handleSwitchMode = () => {
  49. openConfirmModal({
  50. confirmText: t('Switch Mode'),
  51. cancelText: t('Cancel'),
  52. header: (
  53. <h5>
  54. {samplingMode === 'organization'
  55. ? t('Switch to Manual Mode')
  56. : t('Switch to Automatic Mode')}
  57. </h5>
  58. ),
  59. message: (
  60. <Fragment>
  61. <p>
  62. {samplingMode === 'organization'
  63. ? switchToManualMessage
  64. : switchToAutoMessage}
  65. </p>
  66. {samplingMode === 'organization' ? (
  67. <p>{t('You can switch back to automatic mode at any time.')}</p>
  68. ) : (
  69. <p>
  70. {tct(
  71. 'By switching [strong:you will lose your manually defined sample rates].',
  72. {
  73. strong: <strong />,
  74. }
  75. )}
  76. </p>
  77. )}
  78. </Fragment>
  79. ),
  80. onConfirm: () => {
  81. updateOrganization({
  82. samplingMode: samplingMode === 'organization' ? 'project' : 'organization',
  83. });
  84. },
  85. });
  86. };
  87. return (
  88. <FieldGroup
  89. disabled={!hasAccess}
  90. label={t('Sampling Mode')}
  91. help={t('The current configuration mode for dynamic sampling.')}
  92. >
  93. <ControlWrapper>
  94. <SegmentedControl
  95. disabled={!hasAccess || isPending}
  96. label={t('Sampling mode')}
  97. value={samplingMode}
  98. onChange={handleSwitchMode}
  99. >
  100. <SegmentedControl.Item key="organization" textValue={t('Automatic')}>
  101. <LabelWrapper>
  102. {t('Automatic')}
  103. <QuestionTooltip
  104. isHoverable
  105. size="sm"
  106. title={tct(
  107. 'Automatic mode allows you to set a target sample rate for your organization. Sentry automatically adjusts individual project rates to boost small projects and ensure equal visibility. [link:Learn more]',
  108. {
  109. link: (
  110. <ExternalLink href="https://docs.sentry.io/product/performance/retention-priorities/" />
  111. ),
  112. }
  113. )}
  114. />
  115. </LabelWrapper>
  116. </SegmentedControl.Item>
  117. <SegmentedControl.Item key="project" textValue={t('Manual')}>
  118. <LabelWrapper>
  119. {t('Manual')}
  120. <QuestionTooltip
  121. isHoverable
  122. size="sm"
  123. title={tct(
  124. 'Manual mode allows you to set fixed sample rates for each project. [link:Learn more]',
  125. {
  126. link: (
  127. <ExternalLink href="https://docs.sentry.io/product/performance/retention-priorities/" />
  128. ),
  129. }
  130. )}
  131. />
  132. </LabelWrapper>
  133. </SegmentedControl.Item>
  134. </SegmentedControl>
  135. </ControlWrapper>
  136. </FieldGroup>
  137. );
  138. }
  139. const ControlWrapper = styled('div')`
  140. width: max-content;
  141. `;
  142. const LabelWrapper = styled('div')`
  143. display: flex;
  144. align-items: center;
  145. gap: ${space(1)};
  146. `;