Skip to content

Commit 09a0d8b

Browse files
feat(pyreqwest): Support span streaming
1 parent 1f3f3eb commit 09a0d8b

2 files changed

Lines changed: 725 additions & 229 deletions

File tree

sentry_sdk/integrations/pyreqwest.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from sentry_sdk import start_span
66
from sentry_sdk.consts import OP, SPANDATA
77
from sentry_sdk.integrations import DidNotEnable, Integration
8+
from sentry_sdk.traces import StreamedSpan
89
from sentry_sdk.tracing import BAGGAGE_HEADER_NAME
910
from sentry_sdk.tracing_utils import (
1011
add_http_request_source,
1112
add_sentry_baggage_to_headers,
13+
has_span_streaming_enabled,
1214
should_propagate_trace,
1315
)
1416
from sentry_sdk.utils import (
@@ -83,6 +85,44 @@ def _sentry_pyreqwest_span(request: "Request") -> "Generator[Any, None, None]":
8385
with capture_internal_exceptions():
8486
parsed_url = parse_url(str(request.url), sanitize=False)
8587

88+
client = sentry_sdk.get_client()
89+
if has_span_streaming_enabled(client.options):
90+
with sentry_sdk.traces.start_span(
91+
name=f"{request.method} {parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE}",
92+
attributes={
93+
"sentry.op": OP.HTTP_CLIENT,
94+
"sentry.origin": PyreqwestIntegration.origin,
95+
SPANDATA.HTTP_METHOD: request.method,
96+
},
97+
) as span:
98+
if parsed_url is not None:
99+
span.set_attribute("url", parsed_url.url)
100+
span.set_attribute(SPANDATA.HTTP_QUERY, parsed_url.query)
101+
span.set_attribute(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment)
102+
103+
if should_propagate_trace(sentry_sdk.get_client(), str(request.url)):
104+
for (
105+
key,
106+
value,
107+
) in sentry_sdk.get_current_scope().iter_trace_propagation_headers():
108+
logger.debug(
109+
"[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format(
110+
key=key, value=value, url=request.url
111+
)
112+
)
113+
114+
if key == BAGGAGE_HEADER_NAME:
115+
add_sentry_baggage_to_headers(request.headers, value)
116+
else:
117+
request.headers[key] = value
118+
119+
yield span
120+
121+
with capture_internal_exceptions():
122+
add_http_request_source(span)
123+
124+
return
125+
86126
with start_span(
87127
op=OP.HTTP_CLIENT,
88128
name=f"{request.method} {parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE}",
@@ -124,7 +164,14 @@ async def sentry_async_middleware(
124164

125165
with _sentry_pyreqwest_span(request) as span:
126166
response = await next_handler.run(request)
127-
span.set_http_status(response.status)
167+
if isinstance(span, StreamedSpan):
168+
span.status = "error" if response.status >= 400 else "ok"
169+
span.set_attribute(
170+
SPANDATA.HTTP_RESPONSE_STATUS_CODE,
171+
response.status,
172+
)
173+
else:
174+
span.set_http_status(response.status)
128175

129176
return response
130177

@@ -137,6 +184,13 @@ def sentry_sync_middleware(
137184

138185
with _sentry_pyreqwest_span(request) as span:
139186
response = next_handler.run(request)
140-
span.set_http_status(response.status)
187+
if isinstance(span, StreamedSpan):
188+
span.status = "error" if response.status >= 400 else "ok"
189+
span.set_attribute(
190+
SPANDATA.HTTP_RESPONSE_STATUS_CODE,
191+
response.status,
192+
)
193+
else:
194+
span.set_http_status(response.status)
141195

142196
return response

0 commit comments

Comments
 (0)