Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/integrations/boto3/test_trace_propagation.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def test_presigned_urls_do_not_require_sentry_headers(sentry_init):
traces_sample_rate=1.0,
default_integrations=False,
integrations=[Boto3Integration(), StdlibIntegration()],
trace_lifecycle="stream",
)
client = boto3.client( # type: ignore[attr-defined]
"s3",
Expand Down
1 change: 1 addition & 0 deletions tests/integrations/django/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,7 @@ def test_render_spans_queryset_in_data(sentry_init, client, capture_events):
)
],
traces_sample_rate=1.0,
trace_lifecycle="stream",
)
events = capture_events()

Expand Down
1 change: 1 addition & 0 deletions tests/integrations/django/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def test_task_enqueue_returns_result(sentry_init, immediate_backend):
sentry_init(
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

result = add_numbers.enqueue(3, 5)
Expand Down
12 changes: 10 additions & 2 deletions tests/integrations/grpc/test_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,11 @@ def test_grpc_client_and_servers_interceptors_integration(

@pytest.mark.forked
def test_stream_stream(sentry_init):
sentry_init(traces_sample_rate=1.0, integrations=[GRPCIntegration()])
sentry_init(
traces_sample_rate=1.0,
integrations=[GRPCIntegration()],
trace_lifecycle="stream",
)
server, channel = _set_up()

# Use the provided channel
Expand All @@ -444,7 +448,11 @@ def test_stream_unary(sentry_init):
Test to verify stream-stream works.
Tracing not supported for it yet.
"""
sentry_init(traces_sample_rate=1.0, integrations=[GRPCIntegration()])
sentry_init(
traces_sample_rate=1.0,
integrations=[GRPCIntegration()],
trace_lifecycle="stream",
)
server, channel = _set_up()

# Use the provided channel
Expand Down
150 changes: 83 additions & 67 deletions tests/integrations/threading/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,65 +129,72 @@ def do_some_work():
ids=["propagate_scope=True", "propagate_scope=False"],
)
def test_spans_from_multiple_threads(
sentry_init, capture_events, render_span_tree, propagate_scope
sentry_init, capture_items, render_span_tree, propagate_scope
):
sentry_init(
traces_sample_rate=1.0,
integrations=[ThreadingIntegration(propagate_scope=propagate_scope)],
trace_lifecycle="stream",
)
events = capture_events()
items = capture_items("span")

def do_some_work(number):
with sentry_sdk.start_span(
op=f"inner-run-{number}", name=f"Thread: child-{number}"
with sentry_sdk.traces.start_span(
name=f"Thread: child-{number}",
attributes={"sentry.op": f"inner-run-{number}"},
):
pass

threads = []

with sentry_sdk.start_transaction(op="outer-trx"):
with sentry_sdk.traces.start_span(
name="root span", attributes={"sentry.op": "outer-trx"}, parent_span=None
):
for number in range(5):
with sentry_sdk.start_span(
op=f"outer-submit-{number}", name="Thread: main"
with sentry_sdk.traces.start_span(
name="Thread: main",
attributes={"sentry.op": f"outer-submit-{number}"},
):
t = Thread(target=do_some_work, args=(number,))
t.start()
threads.append(t)
t.join()

for t in threads:
t.join()
sentry_sdk.flush()

(event,) = events
spans = [item.payload for item in items]

# Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False
if propagate_scope or getattr(sys.flags, "thread_inherit_context", None):
assert event["type"] == "transaction"
assert render_span_tree(event["spans"], event["contexts"]["trace"]) == dedent(
# Filter to the main trace only (child threads with propagate_scope=False
# create spans on a separate trace that confuse render_span_tree).
root = next(s for s in spans if s.get("is_segment") and s["name"] == "root span")
spans = [s for s in spans if s["trace_id"] == root["trace_id"]]

expects_child_spans = propagate_scope or getattr(
sys.flags, "thread_inherit_context", None
)
if expects_child_spans:
assert render_span_tree(spans) == dedent(
"""\
- op="outer-trx": description=null
- op="outer-submit-0": description="Thread: main"
- op="inner-run-0": description="Thread: child-0"
- op="outer-submit-1": description="Thread: main"
- op="inner-run-1": description="Thread: child-1"
- op="outer-submit-2": description="Thread: main"
- op="inner-run-2": description="Thread: child-2"
- op="outer-submit-3": description="Thread: main"
- op="inner-run-3": description="Thread: child-3"
- op="outer-submit-4": description="Thread: main"
- op="inner-run-4": description="Thread: child-4"\
- sentry.op="outer-trx": name="root span"
- sentry.op="outer-submit-0": name="Thread: main"
- sentry.op="inner-run-0": name="Thread: child-0"
- sentry.op="outer-submit-1": name="Thread: main"
- sentry.op="inner-run-1": name="Thread: child-1"
- sentry.op="outer-submit-2": name="Thread: main"
- sentry.op="inner-run-2": name="Thread: child-2"
- sentry.op="outer-submit-3": name="Thread: main"
- sentry.op="inner-run-3": name="Thread: child-3"
- sentry.op="outer-submit-4": name="Thread: main"
- sentry.op="inner-run-4": name="Thread: child-4"\
"""
)

elif not propagate_scope:
assert event["type"] == "transaction"
assert render_span_tree(event["spans"], event["contexts"]["trace"]) == dedent(
assert render_span_tree(spans) == dedent(
"""\
- op="outer-trx": description=null
- op="outer-submit-0": description="Thread: main"
- op="outer-submit-1": description="Thread: main"
- op="outer-submit-2": description="Thread: main"
- op="outer-submit-3": description="Thread: main"
- op="outer-submit-4": description="Thread: main"\
- sentry.op="outer-trx": name="root span"
- sentry.op="outer-submit-0": name="Thread: main"
- sentry.op="outer-submit-1": name="Thread: main"
- sentry.op="outer-submit-2": name="Thread: main"
- sentry.op="outer-submit-3": name="Thread: main"
- sentry.op="outer-submit-4": name="Thread: main"\
"""
)

Expand All @@ -198,59 +205,68 @@ def do_some_work(number):
ids=["propagate_scope=True", "propagate_scope=False"],
)
def test_spans_from_threadpool(
sentry_init, capture_events, render_span_tree, propagate_scope
sentry_init, capture_items, render_span_tree, propagate_scope
):
sentry_init(
traces_sample_rate=1.0,
integrations=[ThreadingIntegration(propagate_scope=propagate_scope)],
trace_lifecycle="stream",
)
events = capture_events()
items = capture_items("span")

def do_some_work(number):
with sentry_sdk.start_span(
op=f"inner-run-{number}", name=f"Thread: child-{number}"
with sentry_sdk.traces.start_span(
name=f"Thread: child-{number}",
attributes={"sentry.op": f"inner-run-{number}"},
):
pass

with sentry_sdk.start_transaction(op="outer-trx"):
with sentry_sdk.traces.start_span(
name="root span", attributes={"sentry.op": "outer-trx"}, parent_span=None
):
with futures.ThreadPoolExecutor(max_workers=1) as executor:
for number in range(5):
with sentry_sdk.start_span(
op=f"outer-submit-{number}", name="Thread: main"
with sentry_sdk.traces.start_span(
name="Thread: main",
attributes={"sentry.op": f"outer-submit-{number}"},
):
future = executor.submit(do_some_work, number)
future.result()

(event,) = events
sentry_sdk.flush()

spans = [item.payload for item in items]
root = next(s for s in spans if s.get("is_segment") and s["name"] == "root span")
spans = [s for s in spans if s["trace_id"] == root["trace_id"]]

# Free-threaded builds set thread_inherit_context to True, otherwise thread_inherit_context is False
if propagate_scope or getattr(sys.flags, "thread_inherit_context", None):
assert event["type"] == "transaction"
assert render_span_tree(event["spans"], event["contexts"]["trace"]) == dedent(
expects_child_spans = propagate_scope or getattr(
sys.flags, "thread_inherit_context", None
)
if expects_child_spans:
assert render_span_tree(spans) == dedent(
"""\
- op="outer-trx": description=null
- op="outer-submit-0": description="Thread: main"
- op="inner-run-0": description="Thread: child-0"
- op="outer-submit-1": description="Thread: main"
- op="inner-run-1": description="Thread: child-1"
- op="outer-submit-2": description="Thread: main"
- op="inner-run-2": description="Thread: child-2"
- op="outer-submit-3": description="Thread: main"
- op="inner-run-3": description="Thread: child-3"
- op="outer-submit-4": description="Thread: main"
- op="inner-run-4": description="Thread: child-4"\
- sentry.op="outer-trx": name="root span"
- sentry.op="outer-submit-0": name="Thread: main"
- sentry.op="inner-run-0": name="Thread: child-0"
- sentry.op="outer-submit-1": name="Thread: main"
- sentry.op="inner-run-1": name="Thread: child-1"
- sentry.op="outer-submit-2": name="Thread: main"
- sentry.op="inner-run-2": name="Thread: child-2"
- sentry.op="outer-submit-3": name="Thread: main"
- sentry.op="inner-run-3": name="Thread: child-3"
- sentry.op="outer-submit-4": name="Thread: main"
- sentry.op="inner-run-4": name="Thread: child-4"\
"""
)

elif not propagate_scope:
assert event["type"] == "transaction"
assert render_span_tree(event["spans"], event["contexts"]["trace"]) == dedent(
assert render_span_tree(spans) == dedent(
"""\
- op="outer-trx": description=null
- op="outer-submit-0": description="Thread: main"
- op="outer-submit-1": description="Thread: main"
- op="outer-submit-2": description="Thread: main"
- op="outer-submit-3": description="Thread: main"
- op="outer-submit-4": description="Thread: main"\
- sentry.op="outer-trx": name="root span"
- sentry.op="outer-submit-0": name="Thread: main"
- sentry.op="outer-submit-1": name="Thread: main"
- sentry.op="outer-submit-2": name="Thread: main"
- sentry.op="outer-submit-3": name="Thread: main"
- sentry.op="outer-submit-4": name="Thread: main"\
"""
)
Loading