Skip to content

Commit a793322

Browse files
committed
tests
1 parent d68e635 commit a793322

2 files changed

Lines changed: 170 additions & 27 deletions

File tree

‎sentry_sdk/integrations/stdlib.py‎

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,18 @@ def putrequest(
115115
span_streaming = has_span_streaming_enabled(client.options)
116116
span: "Union[Span, StreamedSpan, None]"
117117
breadcrumb: "dict[str, Any]" = {}
118+
118119
if span_streaming:
120+
breadcrumb[SPANDATA.HTTP_REQUEST_METHOD] = method
121+
if parsed_url is not None and should_send_default_pii():
122+
breadcrumb.update(
123+
{
124+
SPANDATA.URL_FRAGMENT: parsed_url.fragment,
125+
SPANDATA.URL_FULL: parsed_url.url,
126+
SPANDATA.URL_QUERY: parsed_url.query,
127+
}
128+
)
129+
119130
if sentry_sdk.traces.get_current_span() is None:
120131
span = None
121132
else:
@@ -131,21 +142,12 @@ def putrequest(
131142
SPANDATA.HTTP_REQUEST_METHOD: method,
132143
},
133144
)
134-
breadcrumb[SPANDATA.HTTP_REQUEST_METHOD] = method
135145

136146
if parsed_url is not None and should_send_default_pii():
137147
span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment)
138148
span.set_attribute(SPANDATA.URL_FULL, parsed_url.url)
139149
span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query)
140150

141-
breadcrumb.update(
142-
{
143-
SPANDATA.URL_FRAGMENT: parsed_url.fragment,
144-
SPANDATA.URL_FULL: parsed_url.url,
145-
SPANDATA.URL_QUERY: parsed_url.query,
146-
}
147-
)
148-
149151
set_on_span = span.set_attribute
150152
else:
151153
span = sentry_sdk.start_span(
@@ -209,31 +211,26 @@ def getresponse(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any":
209211
span = getattr(self, "_sentrysdk_span", None)
210212
breadcrumb = getattr(self, "_sentrysdk_breadcrumb", None) or {}
211213

212-
if span is None:
213-
return real_getresponse(self, *args, **kwargs)
214-
215214
try:
216215
rv = real_getresponse(self, *args, **kwargs)
217216
except BaseException:
218-
_complete_span(span)
217+
if span:
218+
_complete_span(span)
219219
if breadcrumb:
220220
add_http_breadcrumb(None, breadcrumb)
221221
raise
222222

223223
status_code = int(rv.status)
224-
if isinstance(span, StreamedSpan):
225-
span.status = "error" if status_code >= 400 else "ok"
226-
span.set_attribute(SPANDATA.HTTP_STATUS_CODE, status_code)
227-
breadcrumb[SPANDATA.HTTP_STATUS_CODE] = status_code
228-
else:
229-
span.set_http_status(status_code)
230-
span.set_data("reason", rv.reason)
231-
breadcrumb.update(
232-
{
233-
SPANDATA.HTTP_STATUS_CODE: status_code,
234-
"reason": rv.reason,
235-
}
236-
)
224+
breadcrumb[SPANDATA.HTTP_STATUS_CODE] = status_code
225+
226+
if span is not None:
227+
if isinstance(span, StreamedSpan):
228+
span.status = "error" if status_code >= 400 else "ok"
229+
span.set_attribute(SPANDATA.HTTP_STATUS_CODE, status_code)
230+
else:
231+
span.set_http_status(status_code)
232+
span.set_data("reason", rv.reason)
233+
breadcrumb["reason"] = rv.reason
237234

238235
# getresponse doesn't include actually reading the response body. This
239236
# is done in read(). So if the metadata/headers suggest there's a body to
@@ -243,7 +240,8 @@ def getresponse(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any":
243240
rv._sentrysdk_span = span # type: ignore[attr-defined]
244241
rv._sentrysdk_breadcrumb = breadcrumb # type: ignore[attr-defined]
245242
else:
246-
_complete_span(span)
243+
if span:
244+
_complete_span(span)
247245
add_http_breadcrumb(status_code, breadcrumb)
248246

249247
return rv

‎tests/integrations/stdlib/test_httplib.py‎

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,45 @@ def test_crumb_capture(sentry_init, capture_events):
102102
)
103103

104104

105+
@pytest.mark.parametrize("send_default_pii", [True, False])
106+
def test_crumb_capture_span_streaming(sentry_init, capture_events, send_default_pii):
107+
sentry_init(
108+
integrations=[StdlibIntegration()],
109+
trace_lifecycle="stream",
110+
send_default_pii=send_default_pii,
111+
)
112+
events = capture_events()
113+
114+
url = "http://localhost:{}/some/random/url".format(PORT)
115+
urlopen(url)
116+
117+
capture_message("Testing!")
118+
119+
(event,) = events
120+
(crumb,) = event["breadcrumbs"]["values"]
121+
122+
assert crumb["type"] == "http"
123+
assert crumb["category"] == "httplib"
124+
125+
if send_default_pii:
126+
assert crumb["data"] == ApproxDict(
127+
{
128+
SPANDATA.URL_FULL: url,
129+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
130+
SPANDATA.HTTP_STATUS_CODE: 200,
131+
SPANDATA.URL_FRAGMENT: "",
132+
SPANDATA.URL_QUERY: "",
133+
}
134+
)
135+
else:
136+
assert crumb["data"] == ApproxDict(
137+
{
138+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
139+
SPANDATA.HTTP_STATUS_CODE: 200,
140+
}
141+
)
142+
143+
105144
@pytest.mark.parametrize(
106145
"status_code,level",
107146
[
@@ -146,6 +185,65 @@ def test_crumb_capture_client_error(sentry_init, capture_events, status_code, le
146185
)
147186

148187

188+
@pytest.mark.parametrize(
189+
"status_code,level",
190+
[
191+
(200, None),
192+
(301, None),
193+
(403, "warning"),
194+
(405, "warning"),
195+
(500, "error"),
196+
],
197+
)
198+
@pytest.mark.parametrize("send_default_pii", [True, False])
199+
def test_crumb_capture_client_error_span_streaming(
200+
sentry_init, capture_events, status_code, level, send_default_pii
201+
):
202+
sentry_init(
203+
integrations=[StdlibIntegration()],
204+
trace_lifecycle="stream",
205+
send_default_pii=send_default_pii,
206+
)
207+
events = capture_events()
208+
209+
url = f"http://localhost:{PORT}/status/{status_code}" # noqa:E231
210+
try:
211+
urlopen(url)
212+
except HTTPError:
213+
pass
214+
215+
capture_message("Testing!")
216+
217+
(event,) = events
218+
(crumb,) = event["breadcrumbs"]["values"]
219+
220+
assert crumb["type"] == "http"
221+
assert crumb["category"] == "httplib"
222+
223+
if level is None:
224+
assert "level" not in crumb
225+
else:
226+
assert crumb["level"] == level
227+
228+
if send_default_pii:
229+
assert crumb["data"] == ApproxDict(
230+
{
231+
SPANDATA.URL_FULL: url,
232+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
233+
SPANDATA.HTTP_STATUS_CODE: status_code,
234+
SPANDATA.URL_FRAGMENT: "",
235+
SPANDATA.URL_QUERY: "",
236+
}
237+
)
238+
else:
239+
assert crumb["data"] == ApproxDict(
240+
{
241+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
242+
SPANDATA.HTTP_STATUS_CODE: status_code,
243+
}
244+
)
245+
246+
149247
def test_crumb_capture_hint(sentry_init, capture_events):
150248
def before_breadcrumb(crumb, hint):
151249
crumb["data"]["extra"] = "foo"
@@ -180,6 +278,53 @@ def before_breadcrumb(crumb, hint):
180278
)
181279

182280

281+
@pytest.mark.parametrize("send_default_pii", [True, False])
282+
def test_crumb_capture_hint_span_streaming(
283+
sentry_init, capture_events, send_default_pii
284+
):
285+
def before_breadcrumb(crumb, hint):
286+
crumb["data"]["extra"] = "foo"
287+
return crumb
288+
289+
sentry_init(
290+
integrations=[StdlibIntegration()],
291+
before_breadcrumb=before_breadcrumb,
292+
send_default_pii=send_default_pii,
293+
trace_lifecycle="stream",
294+
)
295+
events = capture_events()
296+
297+
url = "http://localhost:{}/some/random/url".format(PORT)
298+
urlopen(url)
299+
300+
capture_message("Testing!")
301+
302+
(event,) = events
303+
(crumb,) = event["breadcrumbs"]["values"]
304+
assert crumb["type"] == "http"
305+
assert crumb["category"] == "httplib"
306+
307+
if send_default_pii:
308+
assert crumb["data"] == ApproxDict(
309+
{
310+
SPANDATA.URL_FULL: url,
311+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
312+
SPANDATA.HTTP_STATUS_CODE: 200,
313+
"extra": "foo",
314+
SPANDATA.URL_FRAGMENT: "",
315+
SPANDATA.URL_QUERY: "",
316+
}
317+
)
318+
else:
319+
assert crumb["data"] == ApproxDict(
320+
{
321+
SPANDATA.HTTP_REQUEST_METHOD: "GET",
322+
SPANDATA.HTTP_STATUS_CODE: 200,
323+
"extra": "foo",
324+
}
325+
)
326+
327+
183328
@pytest.mark.parametrize("span_streaming", [True, False])
184329
def test_empty_realurl(
185330
sentry_init,

0 commit comments

Comments
 (0)