Skip to content

Commit 4e30693

Browse files
authored
test(pyramid): Add span streaming support to integration tests (#6385)
This integration gets span streaming automatically via the SentryWsgiMiddleware and the branching logic in helper methods like `set_transaction_name`. Added test coverage to confirm span streaming works as expected. Fixes PY-2350 Fixes #6048
1 parent 79340b4 commit 4e30693

2 files changed

Lines changed: 108 additions & 12 deletions

File tree

sentry_sdk/integrations/pyramid.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from sentry_sdk.integrations._wsgi_common import RequestExtractor
99
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
1010
from sentry_sdk.scope import should_send_default_pii
11-
from sentry_sdk.tracing import SOURCE_FOR_STYLE
11+
from sentry_sdk.traces import SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE
12+
from sentry_sdk.tracing import SOURCE_FOR_STYLE as TRANSACTION_SOURCE_FOR_STYLE
13+
from sentry_sdk.tracing_utils import has_span_streaming_enabled
1214
from sentry_sdk.utils import (
1315
capture_internal_exceptions,
1416
ensure_integration_enabled,
@@ -157,9 +159,17 @@ def _set_transaction_name_and_source(
157159
"route_name": request.matched_route.name,
158160
"route_pattern": request.matched_route.pattern,
159161
}
162+
is_span_streaming_enabled = has_span_streaming_enabled(
163+
sentry_sdk.get_client().options
164+
)
165+
source = (
166+
SEGMENT_SOURCE_FOR_STYLE[transaction_style]
167+
if is_span_streaming_enabled
168+
else TRANSACTION_SOURCE_FOR_STYLE[transaction_style]
169+
)
160170
scope.set_transaction_name(
161171
name_for_style[transaction_style],
162-
source=SOURCE_FOR_STYLE[transaction_style],
172+
source=source,
163173
)
164174
except Exception:
165175
pass

tests/integrations/pyramid/test_pyramid.py

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
from pyramid.response import Response
1010
from werkzeug.test import Client
1111

12+
import sentry_sdk
1213
from sentry_sdk import add_breadcrumb, capture_message
1314
from sentry_sdk.integrations.pyramid import PyramidIntegration
1415
from sentry_sdk.serializer import MAX_DATABAG_BREADTH
16+
from sentry_sdk.traces import SpanStatus
1517
from tests.conftest import unpack_werkzeug_response
1618

1719
try:
@@ -126,6 +128,7 @@ def hi2(request):
126128
assert event["transaction"] == "hi2"
127129

128130

131+
@pytest.mark.parametrize("span_streaming", [True, False])
129132
@pytest.mark.parametrize(
130133
"url,transaction_style,expected_transaction,expected_source",
131134
[
@@ -139,20 +142,38 @@ def test_transaction_style(
139142
sentry_init,
140143
get_client,
141144
capture_events,
145+
capture_items,
142146
url,
143147
transaction_style,
144148
expected_transaction,
145149
expected_source,
150+
span_streaming,
146151
):
147-
sentry_init(integrations=[PyramidIntegration(transaction_style=transaction_style)])
152+
sentry_init(
153+
integrations=[PyramidIntegration(transaction_style=transaction_style)],
154+
traces_sample_rate=1.0,
155+
_experiments={"trace_lifecycle": "stream" if span_streaming else "static"},
156+
)
157+
158+
if span_streaming:
159+
items = capture_items("event", "span")
160+
else:
161+
events = capture_events()
148162

149-
events = capture_events()
150163
client = get_client()
151164
client.get(url)
152165

153-
(event,) = events
154-
assert event["transaction"] == expected_transaction
155-
assert event["transaction_info"] == {"source": expected_source}
166+
if span_streaming:
167+
sentry_sdk.flush()
168+
spans = [i.payload for i in items if i.type == "span"]
169+
assert len(spans) == 1
170+
(segment,) = spans
171+
assert segment["name"] == expected_transaction
172+
assert segment["attributes"]["sentry.span.source"] == expected_source
173+
else:
174+
(_, transaction_event) = events
175+
assert transaction_event["transaction"] == expected_transaction
176+
assert transaction_event["transaction_info"] == {"source": expected_source}
156177

157178

158179
@pytest.mark.parametrize("max_value_length", [1024, None])
@@ -453,16 +474,81 @@ def index(request):
453474
assert not errors
454475

455476

456-
def test_span_origin(sentry_init, capture_events, get_client):
477+
@pytest.mark.parametrize("span_streaming", [True, False])
478+
def test_tracing_error(
479+
sentry_init, capture_events, capture_items, route, get_client, span_streaming
480+
):
457481
sentry_init(
458482
integrations=[PyramidIntegration()],
459483
traces_sample_rate=1.0,
484+
_experiments={"trace_lifecycle": "stream" if span_streaming else "static"},
460485
)
461-
events = capture_events()
486+
487+
if span_streaming:
488+
items = capture_items("event", "span")
489+
else:
490+
events = capture_events()
491+
492+
@route("/tracing-error")
493+
def tracing_error(request):
494+
1 / 0
462495

463496
client = get_client()
464-
client.get("/message")
497+
with pytest.raises(ZeroDivisionError):
498+
client.get("/tracing-error")
499+
500+
if span_streaming:
501+
sentry_sdk.flush()
502+
spans = [i.payload for i in items if i.type == "span"]
503+
error_events = [i.payload for i in items if i.type == "event"]
504+
505+
assert len(spans) == 1
506+
assert len(error_events) == 1
465507

466-
(_, event) = events
508+
(segment,) = spans
509+
(error_event,) = error_events
467510

468-
assert event["contexts"]["trace"]["origin"] == "auto.http.pyramid"
511+
assert segment["name"] == "tracing_error"
512+
assert segment["status"] == SpanStatus.ERROR
513+
assert segment["attributes"]["sentry.origin"] == "auto.http.pyramid"
514+
515+
assert error_event["exception"]["values"][-1]["type"] == "ZeroDivisionError"
516+
assert error_event["exception"]["values"][-1]["mechanism"]["type"] == "pyramid"
517+
else:
518+
error_event, transaction_event = events
519+
520+
assert transaction_event["type"] == "transaction"
521+
assert transaction_event["transaction"] == "tracing_error"
522+
assert transaction_event["contexts"]["trace"]["status"] == "internal_error"
523+
524+
assert error_event["exception"]["values"][-1]["type"] == "ZeroDivisionError"
525+
assert error_event["exception"]["values"][-1]["mechanism"]["type"] == "pyramid"
526+
527+
528+
@pytest.mark.parametrize("span_streaming", [True, False])
529+
def test_span_origin(
530+
sentry_init, capture_events, capture_items, get_client, span_streaming
531+
):
532+
sentry_init(
533+
integrations=[PyramidIntegration()],
534+
traces_sample_rate=1.0,
535+
_experiments={"trace_lifecycle": "stream" if span_streaming else "static"},
536+
)
537+
538+
if span_streaming:
539+
items = capture_items("event", "span")
540+
else:
541+
events = capture_events()
542+
543+
client = get_client()
544+
client.get("/message")
545+
546+
if span_streaming:
547+
sentry_sdk.flush()
548+
spans = [i.payload for i in items if i.type == "span"]
549+
assert len(spans) == 1
550+
(segment,) = spans
551+
assert segment["attributes"]["sentry.origin"] == "auto.http.pyramid"
552+
else:
553+
(_, event) = events
554+
assert event["contexts"]["trace"]["origin"] == "auto.http.pyramid"

0 commit comments

Comments
 (0)