|
1 | 1 | import gc
|
2 | 2 | from concurrent import futures
|
| 3 | +from textwrap import dedent |
3 | 4 | from threading import Thread
|
4 | 5 |
|
5 | 6 | import pytest
|
@@ -172,3 +173,103 @@ def target():
|
172 | 173 | assert Thread.run.__qualname__ == original_run.__qualname__
|
173 | 174 | assert t.run.__name__ == "run"
|
174 | 175 | assert t.run.__qualname__ == original_run.__qualname__
|
| 176 | + |
| 177 | + |
| 178 | +@pytest.mark.parametrize( |
| 179 | + "propagate_scope", |
| 180 | + (True, False), |
| 181 | + ids=["propagate_scope=True", "propagate_scope=False"], |
| 182 | +) |
| 183 | +def test_scope_data_not_leaked_in_threads(sentry_init, propagate_scope): |
| 184 | + sentry_init( |
| 185 | + integrations=[ThreadingIntegration(propagate_scope=propagate_scope)], |
| 186 | + ) |
| 187 | + |
| 188 | + sentry_sdk.set_tag("initial_tag", "initial_value") |
| 189 | + initial_iso_scope = sentry_sdk.get_isolation_scope() |
| 190 | + |
| 191 | + def do_some_work(): |
| 192 | + # check if we have the initial scope data propagated into the thread |
| 193 | + if propagate_scope: |
| 194 | + assert sentry_sdk.get_isolation_scope()._tags == { |
| 195 | + "initial_tag": "initial_value" |
| 196 | + } |
| 197 | + else: |
| 198 | + assert sentry_sdk.get_isolation_scope()._tags == {} |
| 199 | + |
| 200 | + # change data in isolation scope in thread |
| 201 | + sentry_sdk.set_tag("thread_tag", "thread_value") |
| 202 | + |
| 203 | + t = Thread(target=do_some_work) |
| 204 | + t.start() |
| 205 | + t.join() |
| 206 | + |
| 207 | + # check if the initial scope data is not modified by the started thread |
| 208 | + assert initial_iso_scope._tags == { |
| 209 | + "initial_tag": "initial_value" |
| 210 | + }, "The isolation scope in the main thread should not be modified by the started thread." |
| 211 | + |
| 212 | + |
| 213 | +@pytest.mark.parametrize( |
| 214 | + "propagate_scope", |
| 215 | + (True, False), |
| 216 | + ids=["propagate_scope=True", "propagate_scope=False"], |
| 217 | +) |
| 218 | +def test_spans_from_multiple_threads( |
| 219 | + sentry_init, capture_events, render_span_tree, propagate_scope |
| 220 | +): |
| 221 | + sentry_init( |
| 222 | + traces_sample_rate=1.0, |
| 223 | + integrations=[ThreadingIntegration(propagate_scope=propagate_scope)], |
| 224 | + ) |
| 225 | + events = capture_events() |
| 226 | + |
| 227 | + def do_some_work(number): |
| 228 | + with sentry_sdk.start_span( |
| 229 | + op=f"inner-run-{number}", name=f"Thread: child-{number}" |
| 230 | + ): |
| 231 | + pass |
| 232 | + |
| 233 | + threads = [] |
| 234 | + |
| 235 | + with sentry_sdk.start_transaction(op="outer-trx"): |
| 236 | + for number in range(5): |
| 237 | + with sentry_sdk.start_span( |
| 238 | + op=f"outer-submit-{number}", name="Thread: main" |
| 239 | + ): |
| 240 | + t = Thread(target=do_some_work, args=(number,)) |
| 241 | + t.start() |
| 242 | + threads.append(t) |
| 243 | + |
| 244 | + for t in threads: |
| 245 | + t.join() |
| 246 | + |
| 247 | + (event,) = events |
| 248 | + if propagate_scope: |
| 249 | + assert render_span_tree(event) == dedent( |
| 250 | + """\ |
| 251 | + - op="outer-trx": description=null |
| 252 | + - op="outer-submit-0": description="Thread: main" |
| 253 | + - op="inner-run-0": description="Thread: child-0" |
| 254 | + - op="outer-submit-1": description="Thread: main" |
| 255 | + - op="inner-run-1": description="Thread: child-1" |
| 256 | + - op="outer-submit-2": description="Thread: main" |
| 257 | + - op="inner-run-2": description="Thread: child-2" |
| 258 | + - op="outer-submit-3": description="Thread: main" |
| 259 | + - op="inner-run-3": description="Thread: child-3" |
| 260 | + - op="outer-submit-4": description="Thread: main" |
| 261 | + - op="inner-run-4": description="Thread: child-4"\ |
| 262 | +""" |
| 263 | + ) |
| 264 | + |
| 265 | + elif not propagate_scope: |
| 266 | + assert render_span_tree(event) == dedent( |
| 267 | + """\ |
| 268 | + - op="outer-trx": description=null |
| 269 | + - op="outer-submit-0": description="Thread: main" |
| 270 | + - op="outer-submit-1": description="Thread: main" |
| 271 | + - op="outer-submit-2": description="Thread: main" |
| 272 | + - op="outer-submit-3": description="Thread: main" |
| 273 | + - op="outer-submit-4": description="Thread: main"\ |
| 274 | +""" |
| 275 | + ) |
0 commit comments