diff --git a/src/sentry/utils/rollout.py b/src/sentry/utils/rollout.py index 28bf2d3826f5..e3232252cd3f 100644 --- a/src/sentry/utils/rollout.py +++ b/src/sentry/utils/rollout.py @@ -1,7 +1,7 @@ import logging import random from collections.abc import Callable -from typing import Any, Literal, TypeVar +from typing import Any, Literal, TypeVar, cast from sentry import options from sentry.options import register @@ -154,9 +154,10 @@ def _callsite_mismatch_log_allowlist_option(cls) -> str: def _callsite_use_experimental_data_allowlist_option(cls) -> str: """ This is the callsite-level use-experimental-path rollout option. If the option value - contains a callsite, then that callsite will use the experimental-path data. This should - generally only be used once you've determined that there is a high rate of partial- or - exact- match at the callsite. Defaults to an empty list. + contains a callsite, then that callsite will use the experimental-path data. Use ``*`` to + enable the experimental path for all callsites. This should generally only be used once + you've determined that there is a high rate of partial- or exact-match. Defaults to an + empty list. """ return f"dynamic.saferollouts.{cls.ROLLOUT_NAME}.use_experimental_data_callsite_allowlist" @@ -331,15 +332,16 @@ def should_check_experiment(cls, callsite: str) -> bool: def should_use_experimental_data(cls, callsite: str) -> bool: """ This function controls whether you use the result of your experimental data. Useful for - allowlisting known-safe callsites. + allowlisting known-safe callsites. The special callsite ``*`` allows all callsites. Note: If you are transitioning from an existing, intended-to-be-equivalent dataset, you should instead use `check_and_choose` (which has this check built in and has better logging). """ - use_experimental_data = callsite in options.get( - cls._callsite_use_experimental_data_allowlist_option() + allowlist = cast( + list[str], options.get(cls._callsite_use_experimental_data_allowlist_option()) ) + use_experimental_data = "*" in allowlist or callsite in allowlist tags: dict[str, str] = { "rollout_name": cls.ROLLOUT_NAME, "callsite": callsite, diff --git a/tests/sentry/utils/test_rollout.py b/tests/sentry/utils/test_rollout.py index 3d6dea7e8e94..5c466b2eccd7 100644 --- a/tests/sentry/utils/test_rollout.py +++ b/tests/sentry/utils/test_rollout.py @@ -165,6 +165,14 @@ def test_experimental_data_use(self) -> None: TestRolloutComparator.check_and_choose("ctl", "exp", "known_good_callsite") == "exp" ) + with override_options( + { + TEST_CALLSITE_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: ["*"], + } + ): + assert TestRolloutComparator.check_and_choose("ctl", "exp", "test_3") == "exp" + assert TestRolloutComparator.check_and_choose("ctl", "exp", "other") == "exp" + def test_comparator_use(self) -> None: exact_matcher = lambda control, exp: exp["dogs"] == control["dogs"] close_matcher = lambda control, exp: exp["dogs"].issubset(control["dogs"]) diff --git a/tests/snuba/api/endpoints/test_organization_events_occurrences.py b/tests/snuba/api/endpoints/test_organization_events_occurrences.py index 30d03b2eb854..d65328596925 100644 --- a/tests/snuba/api/endpoints/test_organization_events_occurrences.py +++ b/tests/snuba/api/endpoints/test_organization_events_occurrences.py @@ -27,7 +27,7 @@ def setUp(self) -> None: def request_with_feature_flag(self, payload: dict) -> Response: with self.options( - {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: self.callsite_name} + {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: [self.callsite_name]} ): response = self.do_request({**payload, "dataset": "occurrences"}) assert response.status_code == 200, response.content @@ -526,7 +526,7 @@ def request_with_feature_flag(self, payload: dict) -> Response: "organizations:trace-item-details-array-fields": True, } with self.options( - {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: self.callsite_name} + {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: [self.callsite_name]} ): response = self.do_request({**payload, "dataset": "occurrences"}, features=features) assert response.status_code == 200, response.content @@ -784,7 +784,7 @@ def test_array_fields_dropped_when_feature_flag_off(self) -> None: expected_http_url = expected[0]["http_url"] with self.options( - {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: self.callsite_name} + {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: [self.callsite_name]} ): response = self.do_request( { diff --git a/tests/snuba/api/endpoints/test_organization_events_timeseries_occurrences.py b/tests/snuba/api/endpoints/test_organization_events_timeseries_occurrences.py index cf39da16f849..3b1457e6b59e 100644 --- a/tests/snuba/api/endpoints/test_organization_events_timeseries_occurrences.py +++ b/tests/snuba/api/endpoints/test_organization_events_timeseries_occurrences.py @@ -73,7 +73,7 @@ def _store_occurrences_and_request_timeseries( ] self.store_eap_items(occurrences) with self.options( - {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: self.callsite_name} + {EAP_OCCURRENCES_USE_EXPERIMENTAL_DATA_ALLOWLIST_OPTION: [self.callsite_name]} ): return self._do_request( data={