From 51cf051849bc84da8aeeacc0992fe30fa0d794fc Mon Sep 17 00:00:00 2001 From: Simon Hellmayr Date: Thu, 10 Sep 2026 11:20:23 +0200 Subject: [PATCH] ref(dynamic-sampling): Disable the switch into Advanced Mode Advanced Mode (per-project sample rates) is closed to new organizations; the API now rejects a switch into it. Disable the switch in Automatic Mode and explain why in its tooltip. An organization already in Advanced Mode keeps an enabled switch to leave it. Co-Authored-By: Claude Fable 5.1 --- .../samplingModeSwitch.spec.tsx | 28 ++++++++++++++----- .../dynamicSampling/samplingModeSwitch.tsx | 19 ++++++++----- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/static/app/views/settings/dynamicSampling/samplingModeSwitch.spec.tsx b/static/app/views/settings/dynamicSampling/samplingModeSwitch.spec.tsx index 22d6732c3eb7..26507a9bccd6 100644 --- a/static/app/views/settings/dynamicSampling/samplingModeSwitch.spec.tsx +++ b/static/app/views/settings/dynamicSampling/samplingModeSwitch.spec.tsx @@ -17,14 +17,22 @@ describe('SamplingModeSwitch', () => { MockApiClient.clearMockResponses(); }); - it('renders correctly in organization mode', () => { + it('cannot enter advanced mode from organization mode', async () => { render(, { organization, }); - expect(screen.getByRole('checkbox')).toBeEnabled(); expect(screen.getByText('Advanced Mode')).toBeInTheDocument(); expect(screen.getByRole('checkbox')).not.toBeChecked(); + expect(screen.getByRole('checkbox')).toBeDisabled(); + + await userEvent.hover(screen.getByRole('checkbox')); + expect( + await screen.findByText( + 'Advanced Mode is no longer available. Sample rates are configured for the whole organization.' + ) + ).toBeInTheDocument(); + expect(openSamplingModeSwitchModal).not.toHaveBeenCalled(); }); it('renders correctly in project mode', () => { @@ -33,25 +41,26 @@ describe('SamplingModeSwitch', () => { }); expect(screen.getByRole('checkbox')).toBeChecked(); + expect(screen.getByRole('checkbox')).toBeEnabled(); }); - it('opens modal when switch is clicked', async () => { + it('opens the modal to leave advanced mode when the switch is clicked', async () => { render(, { - organization, + organization: {...organization, samplingMode: 'project'}, }); await userEvent.click(screen.getByRole('checkbox')); expect(openSamplingModeSwitchModal).toHaveBeenCalledWith({ - samplingMode: 'project', + samplingMode: 'organization', initialTargetRate: 0.3, }); }); - it('disables switch when user lacks permission', () => { + it('disables switch when user lacks permission', async () => { const orgWithoutAccess = OrganizationFixture({ access: [], // No project:write access - samplingMode: 'organization', + samplingMode: 'project', }); render(, { @@ -59,5 +68,10 @@ describe('SamplingModeSwitch', () => { }); expect(screen.getByRole('checkbox')).toBeDisabled(); + + await userEvent.hover(screen.getByRole('checkbox')); + expect( + await screen.findByText('You do not have permission to change this setting.') + ).toBeInTheDocument(); }); }); diff --git a/static/app/views/settings/dynamicSampling/samplingModeSwitch.tsx b/static/app/views/settings/dynamicSampling/samplingModeSwitch.tsx index 6ec43922f26d..31069ba49268 100644 --- a/static/app/views/settings/dynamicSampling/samplingModeSwitch.tsx +++ b/static/app/views/settings/dynamicSampling/samplingModeSwitch.tsx @@ -19,14 +19,22 @@ interface Props { export function SamplingModeSwitch({initialTargetRate}: Props) { const {samplingMode} = useOrganization(); const hasAccess = useHasDynamicSamplingWriteAccess(); + // Advanced Mode can no longer be entered. An organization already in it can still leave it. + const isInAdvancedMode = samplingMode === 'project'; const handleSwitchMode = () => { openSamplingModeSwitchModal({ - samplingMode: samplingMode === 'organization' ? 'project' : 'organization', + samplingMode: 'organization', initialTargetRate, }); }; + const disabledReason = isInAdvancedMode + ? t('You do not have permission to change this setting.') + : t( + 'Advanced Mode is no longer available. Sample rates are configured for the whole organization.' + ); + return ( {t('Advanced Mode')} - +