Options

Options are a way to store generic system-wide configuration. They serve a similar purpose to configuration files, but they are backed by a database, so it's possible to change them at runtime without a deploy. Options are stored in the database and cached, so they are performant and reliable. This makes options well-suited for rates, quotas, and limits.

To add a new system option, add it to sentry/options/defaults.py by registering it. e.g.,

Copied
register("performance.some-feature-rate", default=0.0)

Follow these rules when adding new options:

  • namespace your option (e.g., feature-scope.feature-name)
  • colocate your new option with related existing options
  • use dashes and not underscores
  • always set a default value with default=

The value of an option can be any pickleable value.

To check the value of an option, import the options module and use the get method. e.g.,

Copied
from sentry import options
feature_rate = options.get("performance.some-feature-rate")

You can change the value of an option using sentry shell, or by using the options UI.

You can set option values using sentry shell. e.g.,

Copied
sentry shell

then,

Copied
from sentry import options
options.set("performance.some-feature-rate", 0.01)

If you expect to frequently update your option, you can make it editable in the options UI. The /manage/settings page in the Sentry app has inputs for a small set of the available options. You can submit a pull request to add your option to the UI by updating the corresponding React view. The options UI is only available to superusers. Editing options requires the "options.admin" permission, and all changes are added to an audit log.

If you're working on a system-wide feature, you may choose to use options for your rollout instead of feature flags. Unlike feature flags, options don't allow for easy segmentation, but they are performant, stable, and simple to implement. e.g.,

Copied
import random
from sentry import options

rate = options.get("performance.some-feature-rate")
if rate > random.random():
    do_feature_stuff()

However, be careful! Using random.random will cause your feature to be enabled and disabled randomly between page requests. This may be unacceptable for user-facing features. To avoid this, you can use the sample_modulo helper. e.g.,

Copied
from sentry.utils.options import sample_modulo

if sample_modulo("performance.some-feature-rate", organization.id):
    do_feature_stuff()

sample_modulo guarantees that for a given value of the option and a given organization it will always return the same boolean value.

In order to test features that check options, you can use the override_options decorator. e.g.,

Copied
from sentry.testutils.helpers import override_options

@override_options({"performance.some-feature-rate": 1.0})
def test_some_feature(self):
    ...

There is also a matching override_options context manager:

Copied
from sentry.testutils.helpers.options import override_options

def test_some_feature(self):
    with override_options({"performance.some-feature-rate": 1.0}):
        ...

If your option is short-lived, you should remove it once it's no longer needed. First, create a pull request to remove the option and its usage. Once it's merged and deployed, remove the option from the database. To do this, you can use the Sentry shell. e.g.,

Copied
sentry shell

then,

Copied
from sentry import options
options.delete("performance.some-feature-rate")
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").