|
2 | 2 | import concurrent.futures as cf |
3 | 3 |
|
4 | 4 | import sentry_sdk |
| 5 | +from sentry_sdk.integrations import _processed_integrations |
5 | 6 | from sentry_sdk.integrations.featureflags import FeatureFlagsIntegration |
6 | 7 |
|
7 | 8 |
|
8 | | -def test_featureflags_integration(sentry_init): |
| 9 | +def test_featureflags_integration(sentry_init, capture_events): |
| 10 | + _processed_integrations.discard( |
| 11 | + FeatureFlagsIntegration.identifier |
| 12 | + ) # force reinstall |
9 | 13 | sentry_init(integrations=[FeatureFlagsIntegration()]) |
10 | 14 | flags_integration = sentry_sdk.get_client().get_integration(FeatureFlagsIntegration) |
11 | 15 |
|
12 | 16 | flags_integration.set_flag("hello", False) |
13 | 17 | flags_integration.set_flag("world", True) |
14 | 18 | flags_integration.set_flag("other", False) |
15 | 19 |
|
16 | | - assert sentry_sdk.get_current_scope().flags.get() == [ |
17 | | - {"flag": "hello", "result": False}, |
18 | | - {"flag": "world", "result": True}, |
19 | | - {"flag": "other", "result": False}, |
20 | | - ] |
| 20 | + events = capture_events() |
| 21 | + sentry_sdk.capture_exception(Exception("something wrong!")) |
| 22 | + [event] = events |
21 | 23 |
|
| 24 | + assert event["contexts"]["flags"] == { |
| 25 | + "values": [ |
| 26 | + {"flag": "hello", "result": False}, |
| 27 | + {"flag": "world", "result": True}, |
| 28 | + {"flag": "other", "result": False}, |
| 29 | + ] |
| 30 | + } |
22 | 31 |
|
23 | | -def test_featureflags_integration_threaded(sentry_init): |
| 32 | + |
| 33 | +def test_featureflags_integration_threaded(sentry_init, capture_events): |
| 34 | + _processed_integrations.discard( |
| 35 | + FeatureFlagsIntegration.identifier |
| 36 | + ) # force reinstall |
24 | 37 | sentry_init(integrations=[FeatureFlagsIntegration()]) |
| 38 | + events = capture_events() |
| 39 | + |
| 40 | + # Capture an eval before we split isolation scopes. |
25 | 41 | flags_integration = sentry_sdk.get_client().get_integration(FeatureFlagsIntegration) |
| 42 | + flags_integration.set_flag("hello", False) |
26 | 43 |
|
27 | 44 | def task(flag_key): |
28 | 45 | # Creates a new isolation scope for the thread. |
29 | 46 | # This means the evaluations in each task are captured separately. |
30 | 47 | with sentry_sdk.isolation_scope(): |
| 48 | + flags_integration = sentry_sdk.get_client().get_integration( |
| 49 | + FeatureFlagsIntegration |
| 50 | + ) |
31 | 51 | flags_integration.set_flag(flag_key, False) |
32 | | - return sentry_sdk.get_current_scope().flags.get() |
33 | | - |
34 | | - # Capture an eval before we split isolation scopes. |
35 | | - flags_integration.set_flag("hello", False) |
| 52 | + # use a tag to identify to identify events later on |
| 53 | + sentry_sdk.set_tag("flag_key", flag_key) |
| 54 | + sentry_sdk.capture_exception(Exception("something wrong!")) |
36 | 55 |
|
| 56 | + # Run tasks in separate threads |
37 | 57 | with cf.ThreadPoolExecutor(max_workers=2) as pool: |
38 | | - results = list(pool.map(task, ["world", "other"])) |
39 | | - |
40 | | - assert results[0] == [ |
41 | | - {"flag": "hello", "result": False}, |
42 | | - {"flag": "world", "result": False}, |
43 | | - ] |
44 | | - assert results[1] == [ |
45 | | - {"flag": "hello", "result": False}, |
46 | | - {"flag": "other", "result": False}, |
47 | | - ] |
48 | | - |
49 | | - |
50 | | -def test_featureflags_integration_asyncio(sentry_init): |
51 | | - """Assert concurrently evaluated flags do not pollute one another.""" |
| 58 | + pool.map(task, ["world", "other"]) |
| 59 | + |
| 60 | + assert len(events) == 2 |
| 61 | + events.sort(key=lambda e: e["tags"]["flag_key"]) |
| 62 | + assert events[0]["contexts"]["flags"] == { |
| 63 | + "values": [ |
| 64 | + {"flag": "hello", "result": False}, |
| 65 | + {"flag": "other", "result": False}, |
| 66 | + ] |
| 67 | + } |
| 68 | + assert events[1]["contexts"]["flags"] == { |
| 69 | + "values": [ |
| 70 | + {"flag": "hello", "result": False}, |
| 71 | + {"flag": "world", "result": False}, |
| 72 | + ] |
| 73 | + } |
| 74 | + |
| 75 | + |
| 76 | +def test_featureflags_integration_asyncio(sentry_init, capture_events): |
| 77 | + _processed_integrations.discard( |
| 78 | + FeatureFlagsIntegration.identifier |
| 79 | + ) # force reinstall |
52 | 80 | sentry_init(integrations=[FeatureFlagsIntegration()]) |
| 81 | + events = capture_events() |
| 82 | + |
| 83 | + # Capture an eval before we split isolation scopes. |
53 | 84 | flags_integration = sentry_sdk.get_client().get_integration(FeatureFlagsIntegration) |
| 85 | + flags_integration.set_flag("hello", False) |
54 | 86 |
|
55 | 87 | async def task(flag_key): |
| 88 | + # Creates a new isolation scope for the thread. |
| 89 | + # This means the evaluations in each task are captured separately. |
56 | 90 | with sentry_sdk.isolation_scope(): |
| 91 | + flags_integration = sentry_sdk.get_client().get_integration( |
| 92 | + FeatureFlagsIntegration |
| 93 | + ) |
57 | 94 | flags_integration.set_flag(flag_key, False) |
58 | | - return sentry_sdk.get_current_scope().flags.get() |
| 95 | + # use a tag to identify to identify events later on |
| 96 | + sentry_sdk.set_tag("flag_key", flag_key) |
| 97 | + sentry_sdk.capture_exception(Exception("something wrong!")) |
59 | 98 |
|
60 | 99 | async def runner(): |
61 | 100 | return asyncio.gather(task("world"), task("other")) |
62 | 101 |
|
63 | | - flags_integration.set_flag("hello", False) |
64 | | - |
65 | | - results = asyncio.run(runner()).result() |
66 | | - assert results[0] == [ |
67 | | - {"flag": "hello", "result": False}, |
68 | | - {"flag": "world", "result": False}, |
69 | | - ] |
70 | | - assert results[1] == [ |
71 | | - {"flag": "hello", "result": False}, |
72 | | - {"flag": "other", "result": False}, |
73 | | - ] |
| 102 | + asyncio.run(runner()) |
| 103 | + |
| 104 | + assert len(events) == 2 |
| 105 | + events.sort(key=lambda e: e["tags"]["flag_key"]) |
| 106 | + assert events[0]["contexts"]["flags"] == { |
| 107 | + "values": [ |
| 108 | + {"flag": "hello", "result": False}, |
| 109 | + {"flag": "other", "result": False}, |
| 110 | + ] |
| 111 | + } |
| 112 | + assert events[1]["contexts"]["flags"] == { |
| 113 | + "values": [ |
| 114 | + {"flag": "hello", "result": False}, |
| 115 | + {"flag": "world", "result": False}, |
| 116 | + ] |
| 117 | + } |
0 commit comments