organizationRateLimits.tsx 4.0 KB

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