Skip to content

Commit 340ffca

Browse files
authored
chore(features) Expand documentation for sentry.features (#74943)
Expand the documentation for features.handler and features.manager.
1 parent 0ee08a0 commit 340ffca

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed

src/sentry/features/__init__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@
2323
# NOTE: There is no currently established convention for features which do not
2424
# fall under these scopes. Use your best judgment for these.
2525
#
26+
# - Decide if your feature needs to be exposed in API responses or not
27+
# If your feature is not used in the frontend, it is recommended that you don't
28+
# expose the feature flag as feature flag checks add latency and bloat to organization
29+
# details and project details responses.
30+
#
2631
# - Set a default for your features.
2732
#
28-
# Feature defaults are configured in the sentry.conf.server.SENTRY_FEATURES
29-
# module variable. This is the DEFAULT value for a feature, the default may be
30-
# overridden by the logic in the exposed feature.manager.FeatureManager
31-
# instance. See the ``has`` method here for a detailed understanding of how
33+
# Feature defaults are configured with the `default` parameter. Default values
34+
# can also be defined in `settings.SENTRY_FEATURES`. Default values
35+
# are used if no registered handler makes a decision for the feature.
36+
# See the ``has`` method here for a detailed understanding of how
3237
# the default values is overridden.
3338
#
3439
# - Use your feature.

src/sentry/features/handler.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@
1717

1818

1919
class FeatureHandler:
20+
"""
21+
Base class for defining custom logic for feature decisions.
22+
23+
Subclasses should implement `has` and contain the logic
24+
necessary for the feature check.
25+
26+
Generally FeatureHandlers are only implemented in `getsentry.features`
27+
as we don't programatically release features in self-hosted.
28+
"""
29+
2030
features: MutableSet[str] = set()
2131

2232
def __call__(self, feature: Feature, actor: User) -> bool | None:
@@ -50,13 +60,20 @@ def batch_has(
5060
raise NotImplementedError
5161

5262

53-
# It is generally better to extend BatchFeatureHandler if it is possible to do
54-
# the check with no more than the feature name, organization, and actor. If it
55-
# needs to unpack the Feature object and examine the flagged entity, extend
56-
# FeatureHandler directly.
63+
class BatchFeatureHandler(FeatureHandler):
64+
"""
65+
Base class for feature handlers that apply to an organization
66+
and an optional collection of `objects` (e.g. projects).
5767
68+
Subclasses are expected to implement `_check_for_batch` and perform a feature check
69+
using only the organization.
70+
71+
It is generally better to extend BatchFeatureHandler if it is possible to do
72+
the check with no more than the feature name, organization, and actor. If it
73+
needs to unpack the Feature object and examine the flagged entity, extend
74+
FeatureHandler instead.
75+
"""
5876

59-
class BatchFeatureHandler(FeatureHandler):
6077
@abc.abstractmethod
6178
def _check_for_batch(
6279
self, feature_name: str, entity: Organization | User, actor: User

src/sentry/features/manager.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,22 @@ def has_for_batch(
7777
actor: User | None = None,
7878
) -> Mapping[Project, bool]:
7979
"""
80-
Determine in a batch if a feature is enabled.
80+
Determine if a feature is enabled for a batch of objects.
8181
82-
This applies the same procedure as ``FeatureManager.has``, but with a
83-
performance benefit where the objects being checked all belong to the
84-
same organization. The objects are entities (e.g., projects) with the
85-
common parent organization, as would be passed individually to ``has``.
82+
This method enables checking a feature for an organization and a collection
83+
of objects (e.g. projects). Feature handlers for batch checks are expected to
84+
subclass `features.BatchFeatureHandler` and implement `has_for_batch` or
85+
`_check_for_batch`. BatchFeatureHandlers will receive a `FeatureCheckBatch`
86+
that contains the organization and object list.
8687
8788
Feature handlers that depend only on organization attributes, and not
8889
on attributes of the individual objects being checked, will generally
89-
perform faster if this method is used in preference to ``has``.
90+
perform faster if this method is used in instead of ``has``.
9091
91-
The return value is a dictionary with the objects as keys. Each value
92-
is what would be returned if the key were passed to ``has``.
92+
The return value is a dictionary with the objects as keys, and each
93+
value is the result of the feature check on the organization.
9394
94-
The entity handler can handle both batch project/organization
95-
contexts so it'll likely have an entirely different implementation
96-
of this functionality.
95+
This method *does not* work with the `entity_handler`.
9796
9897
>>> FeatureManager.has_for_batch('projects:feature', organization, [project1, project2], actor=request.user)
9998
"""

0 commit comments

Comments
 (0)