organizationRateLimits.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import type {RouteComponentProps} from 'react-router';
  2. import FieldGroup from 'sentry/components/forms/fieldGroup';
  3. import RangeField from 'sentry/components/forms/fields/rangeField';
  4. import Form from 'sentry/components/forms/form';
  5. import Panel from 'sentry/components/panels/panel';
  6. import PanelAlert from 'sentry/components/panels/panelAlert';
  7. import PanelBody from 'sentry/components/panels/panelBody';
  8. import PanelHeader from 'sentry/components/panels/panelHeader';
  9. import {t, tct} from 'sentry/locale';
  10. import type {Organization} from 'sentry/types/organization';
  11. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  12. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  13. export type OrganizationRateLimitProps = RouteComponentProps<{}, {}> & {
  14. organization: Organization;
  15. };
  16. const getRateLimitValues = () => {
  17. const steps: number[] = [];
  18. let i = 0;
  19. while (i <= 1_000_000) {
  20. steps.push(i);
  21. if (i < 10_000) {
  22. i += 1_000;
  23. } else if (i < 100_000) {
  24. i += 10_000;
  25. } else {
  26. i += 100_000;
  27. }
  28. }
  29. return steps;
  30. };
  31. // We can just generate this once
  32. const ACCOUNT_RATE_LIMIT_VALUES = getRateLimitValues();
  33. function OrganizationRateLimit({organization}: OrganizationRateLimitProps) {
  34. // TODO(billy): Update organization.quota in organizationStore with new values
  35. const {quota} = organization;
  36. const {maxRate, maxRateInterval, projectLimit, accountLimit} = quota;
  37. const initialData = {
  38. projectRateLimit: projectLimit || 100,
  39. accountRateLimit: accountLimit,
  40. };
  41. return (
  42. <div>
  43. <SettingsPageHeader title={t('Rate Limits')} />
  44. <Panel>
  45. <PanelHeader>{t('Adjust Limits')}</PanelHeader>
  46. <PanelBody>
  47. <PanelAlert type="info">
  48. {t(`Rate limits allow you to control how much data is stored for this
  49. organization. When a rate is exceeded the system will begin discarding
  50. data until the next interval.`)}
  51. </PanelAlert>
  52. <Form
  53. data-test-id="rate-limit-editor"
  54. saveOnBlur
  55. allowUndo
  56. apiMethod="PUT"
  57. apiEndpoint={`/organizations/${organization.slug}/`}
  58. initialData={initialData}
  59. >
  60. {!maxRate ? (
  61. <RangeField
  62. name="accountRateLimit"
  63. label={t('Account Limit')}
  64. min={0}
  65. max={1000000}
  66. allowedValues={ACCOUNT_RATE_LIMIT_VALUES}
  67. help={t(
  68. 'The maximum number of events to accept across this entire organization.'
  69. )}
  70. placeholder="e.g. 500"
  71. formatLabel={value =>
  72. !value
  73. ? t('No Limit')
  74. : tct('[number] per hour', {
  75. number: value.toLocaleString(),
  76. })
  77. }
  78. />
  79. ) : (
  80. <FieldGroup
  81. label={t('Account Limit')}
  82. help={t(
  83. 'The maximum number of events to accept across this entire organization.'
  84. )}
  85. >
  86. <TextBlock css={{marginBottom: 0}}>
  87. {tct(
  88. 'Your account is limited to a maximum of [maxRate] events per [maxRateInterval] seconds.',
  89. {
  90. maxRate,
  91. maxRateInterval,
  92. }
  93. )}
  94. </TextBlock>
  95. </FieldGroup>
  96. )}
  97. <RangeField
  98. name="projectRateLimit"
  99. label={t('Per-Project Limit')}
  100. help={t(
  101. 'The maximum percentage of the account limit (set above) that an individual project can consume.'
  102. )}
  103. step={5}
  104. min={50}
  105. max={100}
  106. formatLabel={value =>
  107. value !== 100 ? `${value}%` : t('No Limit \u2014 100%')
  108. }
  109. />
  110. </Form>
  111. </PanelBody>
  112. </Panel>
  113. </div>
  114. );
  115. }
  116. export default OrganizationRateLimit;