import {useState} from 'react'; import styled from '@emotion/styled'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {Button} from 'sentry/components/button'; import LoadingError from 'sentry/components/loadingError'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import {Tooltip} from 'sentry/components/tooltip'; import {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {OnRouteLeave} from 'sentry/utils/reactRouter6Compat/onRouteLeave'; import useOrganization from 'sentry/utils/useOrganization'; import {OrganizationSampleRateField} from 'sentry/views/settings/dynamicSampling/organizationSampleRateField'; import {ProjectionPeriodControl} from 'sentry/views/settings/dynamicSampling/projectionPeriodControl'; import {ProjectsPreviewTable} from 'sentry/views/settings/dynamicSampling/projectsPreviewTable'; import {SamplingModeField} from 'sentry/views/settings/dynamicSampling/samplingModeField'; import {useHasDynamicSamplingWriteAccess} from 'sentry/views/settings/dynamicSampling/utils/access'; import {organizationSamplingForm} from 'sentry/views/settings/dynamicSampling/utils/organizationSamplingForm'; import {parsePercent} from 'sentry/views/settings/dynamicSampling/utils/parsePercent'; import { type ProjectionSamplePeriod, useProjectSampleCounts, } from 'sentry/views/settings/dynamicSampling/utils/useProjectSampleCounts'; import {useUpdateOrganization} from 'sentry/views/settings/dynamicSampling/utils/useUpdateOrganization'; const {useFormState, FormProvider} = organizationSamplingForm; const UNSAVED_CHANGES_MESSAGE = t( 'You have unsaved changes, are you sure you want to leave?' ); export function OrganizationSampling() { const organization = useOrganization(); const hasAccess = useHasDynamicSamplingWriteAccess(); const [period, setPeriod] = useState('24h'); const formState = useFormState({ initialValues: { targetSampleRate: ((organization.targetSampleRate ?? 1) * 100)?.toLocaleString(), }, }); const sampleCountsQuery = useProjectSampleCounts({period}); const {mutate: updateOrganization, isPending} = useUpdateOrganization(); const handleSubmit = () => { updateOrganization( { targetSampleRate: parsePercent(formState.fields.targetSampleRate.value), }, { onSuccess: () => { addSuccessMessage(t('Changes applied.')); formState.save(); }, onError: () => { addErrorMessage(t('Unable to save changes. Please try again.')); }, } ); }; const handleReset = () => { formState.reset(); }; return ( locationChange.currentLocation.pathname !== locationChange.nextLocation.pathname && formState.hasChanged } />
event.preventDefault()} noValidate> {t('General Settings')}

{t('Project Preview')}

{tct( 'This table gives you a preview of how your projects will be affected by the target sample rate. The [strong:estimated rates] are based on recent span volume and change continuously.', { strong: , } )}

{t( 'Rates apply to all spans in traces that start in each project, including a portion of spans in connected other projects.' )}

{sampleCountsQuery.isError ? ( ) : ( )} {t('Inactive projects are not listed and will be sampled at 100% initially.')}
); } const FormActions = styled('div')` display: grid; grid-template-columns: repeat(2, max-content); gap: ${space(1)}; justify-content: flex-end; padding-bottom: ${space(4)}; `; const HeadingRow = styled('div')` display: flex; align-items: center; justify-content: space-between; padding-bottom: ${space(1.5)}; & > h4 { margin: 0; } `; const SubTextParagraph = styled('p')` color: ${p => p.theme.subText}; font-size: ${p => p.theme.fontSizeSmall}; `;