Skip to content

Commit c08fd2c

Browse files
fix(anthropic): Set exception info on span when applicable
1 parent dd26abc commit c08fd2c

File tree

2 files changed

+429
-18
lines changed

2 files changed

+429
-18
lines changed

sentry_sdk/integrations/anthropic.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -490,16 +490,18 @@ def _wrap_synchronous_message_iterator(
490490
generator_exit = True
491491
raise
492492
finally:
493+
exc_info = sys.exc_info()
493494
with capture_internal_exceptions():
494495
if not generator_exit and hasattr(stream, "_span"):
495-
_finish_streaming_span(
496+
_set_streaming_output_data(
496497
stream._span,
497498
stream._integration,
498499
stream._model,
499500
stream._usage,
500501
stream._content_blocks,
501502
stream._response_id,
502503
)
504+
stream._span.__exit__(*exc_info)
503505
del stream._span
504506

505507

@@ -538,16 +540,18 @@ async def _wrap_asynchronous_message_iterator(
538540
generator_exit = True
539541
raise
540542
finally:
543+
exc_info = sys.exc_info()
541544
with capture_internal_exceptions():
542545
if not generator_exit and hasattr(stream, "_span"):
543-
_finish_streaming_span(
546+
_set_streaming_output_data(
544547
stream._span,
545548
stream._integration,
546549
stream._model,
547550
stream._usage,
548551
stream._content_blocks,
549552
stream._response_id,
550553
)
554+
stream._span.__exit__(*exc_info)
551555
del stream._span
552556

553557

@@ -560,7 +564,6 @@ def _set_output_data(
560564
cache_read_input_tokens: "int | None",
561565
cache_write_input_tokens: "int | None",
562566
content_blocks: "list[Any]",
563-
finish_span: bool = False,
564567
response_id: "str | None" = None,
565568
) -> None:
566569
"""
@@ -601,9 +604,6 @@ def _set_output_data(
601604
input_tokens_cache_write=cache_write_input_tokens,
602605
)
603606

604-
if finish_span:
605-
span.__exit__(None, None, None)
606-
607607

608608
def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "Any":
609609
integration = kwargs.pop("integration")
@@ -663,9 +663,9 @@ def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "A
663663
cache_read_input_tokens=cache_read_input_tokens,
664664
cache_write_input_tokens=cache_write_input_tokens,
665665
content_blocks=content_blocks,
666-
finish_span=True,
667666
response_id=getattr(result, "id", None),
668667
)
668+
span.__exit__(None, None, None)
669669
else:
670670
span.set_data("unknown_response", True)
671671
span.__exit__(None, None, None)
@@ -743,7 +743,7 @@ def _accumulate_event_data(
743743
stream._response_id = response_id
744744

745745

746-
def _finish_streaming_span(
746+
def _set_streaming_output_data(
747747
span: "Span",
748748
integration: "AnthropicIntegration",
749749
model: "Optional[str]",
@@ -752,7 +752,7 @@ def _finish_streaming_span(
752752
response_id: "Optional[str]",
753753
) -> None:
754754
"""
755-
Set output attributes on the AI Client Span and end the span.
755+
Set output attributes on the AI Client Span.
756756
"""
757757
# Anthropic's input_tokens excludes cached/cache_write tokens.
758758
# Normalize to total input tokens for correct cost calculations.
@@ -771,7 +771,6 @@ def _finish_streaming_span(
771771
cache_read_input_tokens=usage.cache_read_input_tokens,
772772
cache_write_input_tokens=usage.cache_write_input_tokens,
773773
content_blocks=[{"text": "".join(content_blocks), "type": "text"}],
774-
finish_span=True,
775774
response_id=response_id,
776775
)
777776

@@ -815,14 +814,15 @@ def __next__(self: "Stream") -> "RawMessageStreamEvent":
815814
if not hasattr(self, "_span"):
816815
raise
817816

818-
_finish_streaming_span(
817+
_set_streaming_output_data(
819818
self._span,
820819
self._integration,
821820
self._model,
822821
self._usage,
823822
self._content_blocks,
824823
self._response_id,
825824
)
825+
self._span.__exit__(None, None, None)
826826
del self._span
827827
reraise(*exc_info)
828828

@@ -847,14 +847,15 @@ def close(self: "Stream") -> None:
847847
self._span.__exit__(None, None, None)
848848
return f(self)
849849

850-
_finish_streaming_span(
850+
_set_streaming_output_data(
851851
self._span,
852852
self._integration,
853853
self._model,
854854
self._usage,
855855
self._content_blocks,
856856
self._response_id,
857857
)
858+
self._span.__exit__(None, None, None)
858859
del self._span
859860

860861
return f(self)
@@ -941,14 +942,15 @@ async def __anext__(self: "AsyncStream") -> "RawMessageStreamEvent":
941942
if not hasattr(self, "_span"):
942943
raise
943944

944-
_finish_streaming_span(
945+
_set_streaming_output_data(
945946
self._span,
946947
self._integration,
947948
self._model,
948949
self._usage,
949950
self._content_blocks,
950951
self._response_id,
951952
)
953+
self._span.__exit__(None, None, None)
952954
del self._span
953955
reraise(*exc_info)
954956

@@ -973,14 +975,15 @@ async def close(self: "Stream") -> None:
973975
self._span.__exit__(None, None, None)
974976
return await f(self)
975977

976-
_finish_streaming_span(
978+
_set_streaming_output_data(
977979
self._span,
978980
self._integration,
979981
self._model,
980982
self._usage,
981983
self._content_blocks,
982984
self._response_id,
983985
)
986+
self._span.__exit__(None, None, None)
984987
del self._span
985988

986989
return await f(self)
@@ -1104,14 +1107,15 @@ def __next__(self: "MessageStream") -> "MessageStreamEvent":
11041107
if not hasattr(self, "_span"):
11051108
raise
11061109

1107-
_finish_streaming_span(
1110+
_set_streaming_output_data(
11081111
self._span,
11091112
self._integration,
11101113
self._model,
11111114
self._usage,
11121115
self._content_blocks,
11131116
self._response_id,
11141117
)
1118+
self._span.__exit__(None, None, None)
11151119
del self._span
11161120
reraise(*exc_info)
11171121

@@ -1136,14 +1140,15 @@ def close(self: "MessageStream") -> None:
11361140
self._span.__exit__(None, None, None)
11371141
return f(self)
11381142

1139-
_finish_streaming_span(
1143+
_set_streaming_output_data(
11401144
self._span,
11411145
self._integration,
11421146
self._model,
11431147
self._usage,
11441148
self._content_blocks,
11451149
self._response_id,
11461150
)
1151+
self._span.__exit__(None, None, None)
11471152
del self._span
11481153

11491154
return f(self)
@@ -1275,14 +1280,15 @@ async def __anext__(self: "AsyncMessageStream") -> "MessageStreamEvent":
12751280
if not hasattr(self, "_span"):
12761281
raise
12771282

1278-
_finish_streaming_span(
1283+
_set_streaming_output_data(
12791284
self._span,
12801285
self._integration,
12811286
self._model,
12821287
self._usage,
12831288
self._content_blocks,
12841289
self._response_id,
12851290
)
1291+
self._span.__exit__(None, None, None)
12861292
del self._span
12871293
reraise(*exc_info)
12881294

@@ -1307,14 +1313,15 @@ async def close(self: "AsyncMessageStream") -> None:
13071313
self._span.__exit__(None, None, None)
13081314
return await f(self)
13091315

1310-
_finish_streaming_span(
1316+
_set_streaming_output_data(
13111317
self._span,
13121318
self._integration,
13131319
self._model,
13141320
self._usage,
13151321
self._content_blocks,
13161322
self._response_id,
13171323
)
1324+
self._span.__exit__(None, None, None)
13181325
del self._span
13191326

13201327
return await f(self)

0 commit comments

Comments
 (0)