88from sentry_sdk .consts import OP , SPANDATA
99from sentry_sdk .integrations import Integration
1010from sentry_sdk .scope import add_global_event_processor
11+ from sentry_sdk .traces import StreamedSpan
1112from sentry_sdk .tracing_utils import (
1213 EnvironHeaders ,
1314 should_propagate_trace ,
1415 add_http_request_source ,
16+ has_span_streaming_enabled ,
1517)
1618from sentry_sdk .utils import (
1719 SENSITIVE_DATA_SUBSTITUTE ,
@@ -86,6 +88,8 @@ def putrequest(
8688 ):
8789 return real_putrequest (self , method , url , * args , ** kwargs )
8890
91+ span_streaming = has_span_streaming_enabled (client .options )
92+
8993 real_url = url
9094 if real_url is None or not real_url .startswith (("http://" , "https://" )):
9195 real_url = "%s://%s%s%s" % (
@@ -99,22 +103,44 @@ def putrequest(
99103 with capture_internal_exceptions ():
100104 parsed_url = parse_url (real_url , sanitize = False )
101105
102- span = sentry_sdk .start_span (
103- op = OP .HTTP_CLIENT ,
104- name = "%s %s"
105- % (method , parsed_url .url if parsed_url else SENSITIVE_DATA_SUBSTITUTE ),
106- origin = "auto.http.stdlib.httplib" ,
107- )
108- span .set_data (SPANDATA .HTTP_METHOD , method )
109- if parsed_url is not None :
110- span .set_data ("url" , parsed_url .url )
111- span .set_data (SPANDATA .HTTP_QUERY , parsed_url .query )
112- span .set_data (SPANDATA .HTTP_FRAGMENT , parsed_url .fragment )
113-
114- # for proxies, these point to the proxy host/port
115- if tunnel_host :
116- span .set_data (SPANDATA .NETWORK_PEER_ADDRESS , self .host )
117- span .set_data (SPANDATA .NETWORK_PEER_PORT , self .port )
106+ if span_streaming :
107+ span = sentry_sdk .traces .start_span (
108+ name = f"{ method } { parsed_url .url if parsed_url else SENSITIVE_DATA_SUBSTITUTE } "
109+ )
110+ span .set_op (OP .HTTP_CLIENT )
111+ span .set_origin ("auto.http.stdlib.httplib" )
112+
113+ span .set_attribute (SPANDATA .HTTP_METHOD , method )
114+ if parsed_url is not None :
115+ span .set_attribute ("url" , parsed_url .url )
116+ span .set_attribute (SPANDATA .HTTP_QUERY , parsed_url .query )
117+ span .set_attribute (SPANDATA .HTTP_FRAGMENT , parsed_url .fragment )
118+
119+ # for proxies, these point to the proxy host/port
120+ if tunnel_host :
121+ span .set_attribute (SPANDATA .NETWORK_PEER_ADDRESS , self .host )
122+ span .set_attribute (SPANDATA .NETWORK_PEER_PORT , self .port )
123+
124+ span .start ()
125+
126+ else :
127+ span = sentry_sdk .start_span (
128+ op = OP .HTTP_CLIENT ,
129+ name = "%s %s"
130+ % (method , parsed_url .url if parsed_url else SENSITIVE_DATA_SUBSTITUTE ),
131+ origin = "auto.http.stdlib.httplib" ,
132+ )
133+
134+ span .set_data (SPANDATA .HTTP_METHOD , method )
135+ if parsed_url is not None :
136+ span .set_data ("url" , parsed_url .url )
137+ span .set_data (SPANDATA .HTTP_QUERY , parsed_url .query )
138+ span .set_data (SPANDATA .HTTP_FRAGMENT , parsed_url .fragment )
139+
140+ # for proxies, these point to the proxy host/port
141+ if tunnel_host :
142+ span .set_data (SPANDATA .NETWORK_PEER_ADDRESS , self .host )
143+ span .set_data (SPANDATA .NETWORK_PEER_PORT , self .port )
118144
119145 rv = real_putrequest (self , method , url , * args , ** kwargs )
120146
@@ -146,7 +172,10 @@ def getresponse(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any":
146172 rv = real_getresponse (self , * args , ** kwargs )
147173
148174 span .set_http_status (int (rv .status ))
149- span .set_data ("reason" , rv .reason )
175+ if isinstance (span , StreamedSpan ):
176+ span .set_attribute ("reason" , rv .reason )
177+ else :
178+ span .set_data ("reason" , rv .reason )
150179 finally :
151180 span .finish ()
152181
@@ -226,11 +255,23 @@ def sentry_patched_popen_init(
226255
227256 env = None
228257
229- with sentry_sdk .start_span (
230- op = OP .SUBPROCESS ,
231- name = description ,
232- origin = "auto.subprocess.stdlib.subprocess" ,
233- ) as span :
258+ client = sentry_sdk .get_client ()
259+ span_streaming = has_span_streaming_enabled (client .options )
260+
261+ if span_streaming :
262+ span = sentry_sdk .traces .start_span (
263+ name = description ,
264+ )
265+ span .set_op (OP .SUBPROCESS )
266+ span .set_origin ("auto.subprocess.stdlib.subprocess" )
267+ else :
268+ span = sentry_sdk .start_span (
269+ op = OP .SUBPROCESS ,
270+ name = description ,
271+ origin = "auto.subprocess.stdlib.subprocess" ,
272+ )
273+
274+ with span :
234275 for k , v in sentry_sdk .get_current_scope ().iter_trace_propagation_headers (
235276 span = span
236277 ):
@@ -245,11 +286,18 @@ def sentry_patched_popen_init(
245286 env ["SUBPROCESS_" + k .upper ().replace ("-" , "_" )] = v
246287
247288 if cwd :
248- span .set_data ("subprocess.cwd" , cwd )
289+ if span_streaming :
290+ span .set_attribute ("subprocess.cwd" , cwd )
291+ else :
292+ span .set_data ("subprocess.cwd" , cwd )
249293
250294 rv = old_popen_init (self , * a , ** kw )
251295
252- span .set_tag ("subprocess.pid" , self .pid )
296+ if span_streaming :
297+ span .set_attribute ("subprocess.pid" , self .pid )
298+ else :
299+ span .set_tag ("subprocess.pid" , self .pid )
300+
253301 return rv
254302
255303 subprocess .Popen .__init__ = sentry_patched_popen_init # type: ignore
@@ -260,11 +308,22 @@ def sentry_patched_popen_init(
260308 def sentry_patched_popen_wait (
261309 self : "subprocess.Popen[Any]" , * a : "Any" , ** kw : "Any"
262310 ) -> "Any" :
263- with sentry_sdk .start_span (
264- op = OP .SUBPROCESS_WAIT ,
265- origin = "auto.subprocess.stdlib.subprocess" ,
266- ) as span :
311+ client = sentry_sdk .get_client ()
312+ span_streaming = has_span_streaming_enabled (client .options )
313+
314+ if span_streaming :
315+ span = sentry_sdk .traces .start_span (name = "subprocess popen" )
316+ span .set_op (OP .SUBPROCESS_WAIT )
317+ span .set_origin ("auto.subprocess.stdlib.subprocess" )
318+ span .set_tag ("subprocess.pid" , self .pid )
319+ else :
320+ span = sentry_sdk .start_span (
321+ op = OP .SUBPROCESS_WAIT ,
322+ origin = "auto.subprocess.stdlib.subprocess" ,
323+ )
267324 span .set_tag ("subprocess.pid" , self .pid )
325+
326+ with span :
268327 return old_popen_wait (self , * a , ** kw )
269328
270329 subprocess .Popen .wait = sentry_patched_popen_wait # type: ignore
@@ -275,11 +334,24 @@ def sentry_patched_popen_wait(
275334 def sentry_patched_popen_communicate (
276335 self : "subprocess.Popen[Any]" , * a : "Any" , ** kw : "Any"
277336 ) -> "Any" :
278- with sentry_sdk .start_span (
279- op = OP .SUBPROCESS_COMMUNICATE ,
280- origin = "auto.subprocess.stdlib.subprocess" ,
281- ) as span :
337+ client = sentry_sdk .get_client ()
338+ span_streaming = has_span_streaming_enabled (client .options )
339+
340+ if span_streaming :
341+ span = sentry_sdk .traces .start_span (
342+ name = "subprocess communicate" ,
343+ )
344+ span .set_op (OP .SUBPROCESS_COMMUNICATE )
345+ span .set_origin ("auto.subprocess.stdlib.subprocess" )
282346 span .set_tag ("subprocess.pid" , self .pid )
347+ else :
348+ span = sentry_sdk .start_span (
349+ op = OP .SUBPROCESS_COMMUNICATE ,
350+ origin = "auto.subprocess.stdlib.subprocess" ,
351+ )
352+ span .set_tag ("subprocess.pid" , self .pid )
353+
354+ with span :
283355 return old_popen_communicate (self , * a , ** kw )
284356
285357 subprocess .Popen .communicate = sentry_patched_popen_communicate # type: ignore
0 commit comments