Skip to content

Commit 52be6a4

Browse files
committed
add _finish_active_http_child_span to end HTTP spans in Boto3 integration in correct order
1 parent 4e33d2a commit 52be6a4

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

‎sentry_sdk/integrations/boto3/_client.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from sentry_sdk.integrations.boto3 import Boto3Integration
66
from sentry_sdk.integrations.boto3._context import AwsCallContext
77
from sentry_sdk.integrations.boto3._instrumentation import (
8+
_finish_active_http_child_span,
89
_finish_client_span,
910
_sentry_before_sign,
1011
_sentry_request_created,
@@ -65,11 +66,13 @@ def sentry_patched_make_api_call(
6566
except BaseException as exc:
6667
if span is not None:
6768
with capture_internal_exceptions():
69+
_finish_active_http_child_span(span)
6870
span.__exit__(type(exc), exc, exc.__traceback__)
6971
raise
7072

7173
if span is not None:
7274
with capture_internal_exceptions():
75+
_finish_active_http_child_span(span)
7376
_finish_client_span(span, parsed)
7477
return parsed
7578

‎sentry_sdk/integrations/boto3/_instrumentation.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434

3535
_AWS_RPC_SYSTEM_NAME = "aws-api"
36+
_STDLIB_HTTP_SPAN_ORIGIN = "auto.http.stdlib.httplib"
3637

3738

3839
def _set_span_attributes(
@@ -140,6 +141,30 @@ def _start_client_span(
140141
return span
141142

142143

144+
def _finish_active_http_child_span(
145+
span: "Union[Span, StreamedSpan]",
146+
) -> None:
147+
if not isinstance(span, StreamedSpan):
148+
return
149+
150+
http_span = sentry_sdk.traces.get_current_span()
151+
if (
152+
http_span is None
153+
or http_span is span
154+
or http_span.get_attributes().get(SPANDATA.SENTRY_ORIGIN)
155+
!= _STDLIB_HTTP_SPAN_ORIGIN
156+
or http_span._parent_span_id != span.span_id
157+
):
158+
return
159+
160+
# Stdlib normally keeps its HTTP span open until the response body is read.
161+
# Boto3 has a separate `http.client.stream` span for that work, so finish the
162+
# HTTP span after the headers and preserve LIFO scope restoration. OTel permits
163+
# HTTP client spans to end after response headers are read.
164+
# https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client-span-duration
165+
http_span.end()
166+
167+
143168
def _finish_client_span(
144169
span: "Union[Span, StreamedSpan]",
145170
parsed: "Dict[str, Any]",

0 commit comments

Comments
 (0)