Skip to content

Commit 060b2cf

Browse files
authored
Fix feature flags in potel (#4353)
Store feature flags on the isolation scope, that is the correct place. I also checked back with Colton about the behavior of feature flags, and having the flags on the isolation scope (meaning: one set of flags per request-response cycle) is the expected behavior.
1 parent f1a3b23 commit 060b2cf

File tree

5 files changed

+100
-3
lines changed

5 files changed

+100
-3
lines changed

.github/workflows/test-integrations-ai.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.7","3.9","3.11","3.12"]
32+
python-version: ["3.9","3.11","3.12"]
3333
os: [ubuntu-22.04]
3434
steps:
3535
- uses: actions/[email protected]

.github/workflows/test-integrations-misc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.7","3.8","3.10","3.11","3.12","3.13"]
32+
python-version: ["3.7","3.8","3.9","3.10","3.11","3.12","3.13"]
3333
os: [ubuntu-22.04]
3434
steps:
3535
- uses: actions/[email protected]

sentry_sdk/feature_flags.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def add_feature_flag(flag, result):
6464
Records a flag and its value to be sent on subsequent error events.
6565
We recommend you do this on flag evaluations. Flags are buffered per Sentry scope.
6666
"""
67-
flags = sentry_sdk.get_current_scope().flags
67+
flags = sentry_sdk.get_isolation_scope().flags
6868
flags.set(flag, result)
6969

7070
span = sentry_sdk.get_current_span()

tests/integrations/fastapi/test_fastapi.py

+40
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from fastapi.testclient import TestClient
1111
from fastapi.middleware.trustedhost import TrustedHostMiddleware
1212

13+
import sentry_sdk
1314
from sentry_sdk import capture_message
15+
from sentry_sdk.feature_flags import add_feature_flag
1416
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
1517
from sentry_sdk.integrations.fastapi import FastApiIntegration
1618
from sentry_sdk.integrations.starlette import StarletteIntegration
@@ -671,3 +673,41 @@ async def subapp_route():
671673
assert event["transaction"] == "/subapp"
672674
else:
673675
assert event["transaction"].endswith("subapp_route")
676+
677+
678+
@pytest.mark.asyncio
679+
async def test_feature_flags(sentry_init, capture_events):
680+
sentry_init(
681+
traces_sample_rate=1.0,
682+
integrations=[StarletteIntegration(), FastApiIntegration()],
683+
)
684+
685+
events = capture_events()
686+
687+
app = FastAPI()
688+
689+
@app.get("/error")
690+
async def _error():
691+
add_feature_flag("hello", False)
692+
693+
with sentry_sdk.start_span(name="test-span"):
694+
with sentry_sdk.start_span(name="test-span-2"):
695+
raise ValueError("something is wrong!")
696+
697+
try:
698+
client = TestClient(app)
699+
client.get("/error")
700+
except ValueError:
701+
pass
702+
703+
found = False
704+
for event in events:
705+
if "exception" in event.keys():
706+
assert event["contexts"]["flags"] == {
707+
"values": [
708+
{"flag": "hello", "result": False},
709+
]
710+
}
711+
found = True
712+
713+
assert found, "No event with exception found"

tests/test_feature_flags.py

+57
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,63 @@ def test_featureflags_integration(sentry_init, capture_events, uninstall_integra
3131
}
3232

3333

34+
@pytest.mark.asyncio
35+
async def test_featureflags_integration_spans_async(sentry_init, capture_events):
36+
sentry_init(
37+
traces_sample_rate=1.0,
38+
)
39+
events = capture_events()
40+
41+
add_feature_flag("hello", False)
42+
43+
try:
44+
with sentry_sdk.start_span(name="test-span"):
45+
with sentry_sdk.start_span(name="test-span-2"):
46+
raise ValueError("something wrong!")
47+
except ValueError as e:
48+
sentry_sdk.capture_exception(e)
49+
50+
found = False
51+
for event in events:
52+
if "exception" in event.keys():
53+
assert event["contexts"]["flags"] == {
54+
"values": [
55+
{"flag": "hello", "result": False},
56+
]
57+
}
58+
found = True
59+
60+
assert found, "No event with exception found"
61+
62+
63+
def test_featureflags_integration_spans_sync(sentry_init, capture_events):
64+
sentry_init(
65+
traces_sample_rate=1.0,
66+
)
67+
events = capture_events()
68+
69+
add_feature_flag("hello", False)
70+
71+
try:
72+
with sentry_sdk.start_span(name="test-span"):
73+
with sentry_sdk.start_span(name="test-span-2"):
74+
raise ValueError("something wrong!")
75+
except ValueError as e:
76+
sentry_sdk.capture_exception(e)
77+
78+
found = False
79+
for event in events:
80+
if "exception" in event.keys():
81+
assert event["contexts"]["flags"] == {
82+
"values": [
83+
{"flag": "hello", "result": False},
84+
]
85+
}
86+
found = True
87+
88+
assert found, "No event with exception found"
89+
90+
3491
def test_featureflags_integration_threaded(
3592
sentry_init, capture_events, uninstall_integration
3693
):

0 commit comments

Comments
 (0)