diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index c764605c45..fe5bc7e327 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -13,6 +13,7 @@ from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import ( EnvironHeaders, + add_http_breadcrumb, add_http_request_source, has_span_streaming_enabled, should_propagate_trace, @@ -174,6 +175,10 @@ def putrequest( self.putheader(key, value) self._sentrysdk_span = span # type: ignore[attr-defined] + self._sentrysdk_method = method # type: ignore[attr-defined] + self._sentrysdk_url = parsed_url.url if parsed_url else None # type: ignore[attr-defined] + self._sentrysdk_query = parsed_url.query if parsed_url else None # type: ignore[attr-defined] + self._sentrysdk_fragment = parsed_url.fragment if parsed_url else None # type: ignore[attr-defined] return rv @@ -189,14 +194,27 @@ def getresponse(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any": _complete_span(span) raise + status_code = int(rv.status) if isinstance(span, StreamedSpan): - status_code = int(rv.status) span.status = "error" if status_code >= 400 else "ok" span.set_attribute("http.response.status_code", status_code) else: - span.set_http_status(int(rv.status)) + span.set_http_status(status_code) span.set_data("reason", rv.reason) + with capture_internal_exceptions(): + add_http_breadcrumb( + status_code, + { + SPANDATA.HTTP_METHOD: getattr(self, "_sentrysdk_method", None), + "url": getattr(self, "_sentrysdk_url", None), + SPANDATA.HTTP_QUERY: getattr(self, "_sentrysdk_query", None), + SPANDATA.HTTP_FRAGMENT: getattr(self, "_sentrysdk_fragment", None), + SPANDATA.HTTP_STATUS_CODE: status_code, + "reason": rv.reason, + }, + ) + # getresponse doesn't include actually reading the response body. This # is done in read(). So if the metadata/headers suggest there's a body to # read, don't finish the span just yet, but save it for ending it later. diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 5c088b936b..aab2794621 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -700,8 +700,6 @@ def finish( if has_ai_op or is_ai_span_op: self.set_data("gen_ai.conversation.id", conversation_id) - maybe_create_breadcrumbs_from_span(scope, self) - return None def to_json(self) -> "Dict[str, Any]": @@ -1495,5 +1493,4 @@ def calculate_interest_rate(amount, rate, years): extract_sentrytrace_data, has_span_streaming_enabled, has_tracing_enabled, - maybe_create_breadcrumbs_from_span, ) diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index bc286be2ef..d9aad3b12a 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -219,32 +219,12 @@ def add_http_breadcrumb(status_code, data): elif 400 <= status_code <= 499: level = "warning" - kwargs = {"type": "http", "category": "httplib", "data": data} + kwargs: "dict[str, Any]" = {"type": "http", "category": "httplib", "data": data} if level: kwargs["level"] = level sentry_sdk.add_breadcrumb(**kwargs) -def maybe_create_breadcrumbs_from_span( - scope: "sentry_sdk.Scope", span: "sentry_sdk.tracing.Span" -) -> None: - if span.op == OP.HTTP_CLIENT: - level = None - status_code = span._data.get(SPANDATA.HTTP_STATUS_CODE) - if status_code: - if 500 <= status_code <= 599: - level = "error" - elif 400 <= status_code <= 499: - level = "warning" - - if level: - scope.add_breadcrumb( - type="http", category="httplib", data=span._data, level=level - ) - else: - scope.add_breadcrumb(type="http", category="httplib", data=span._data) - - def _get_frame_module_abs_path(frame: "FrameType") -> "Optional[str]": try: return frame.f_code.co_filename