Skip to content

Commit f228d7e

Browse files
ref(anthropic): Separate sync and async .create() patches
1 parent f963475 commit f228d7e

File tree

1 file changed

+92
-50
lines changed

1 file changed

+92
-50
lines changed

sentry_sdk/integrations/anthropic.py

Lines changed: 92 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,10 @@ def _set_output_data(
600600
)
601601

602602

603-
def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "Any":
603+
def _sentry_patched_create_sync(f: "Any", *args: "Any", **kwargs: "Any") -> "Any":
604+
"""
605+
Creates and manages an AI Client Span for both non-streaming and streaming calls.
606+
"""
604607
integration = kwargs.pop("integration")
605608
if integration is None:
606609
return f(*args, **kwargs)
@@ -624,7 +627,13 @@ def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "A
624627

625628
_set_create_input_data(span, kwargs, integration)
626629

627-
result = yield f, args, kwargs
630+
try:
631+
result = f(*args, **kwargs)
632+
except Exception as exc:
633+
exc_info = sys.exc_info()
634+
with capture_internal_exceptions():
635+
_capture_exception(exc)
636+
reraise(*exc_info)
628637

629638
if isinstance(result, Stream):
630639
result._span = span
@@ -638,6 +647,81 @@ def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "A
638647

639648
return result
640649

650+
with capture_internal_exceptions():
651+
if hasattr(result, "content"):
652+
(
653+
input_tokens,
654+
output_tokens,
655+
cache_read_input_tokens,
656+
cache_write_input_tokens,
657+
) = _get_token_usage(result)
658+
659+
content_blocks = []
660+
for content_block in result.content:
661+
if hasattr(content_block, "to_dict"):
662+
content_blocks.append(content_block.to_dict())
663+
elif hasattr(content_block, "model_dump"):
664+
content_blocks.append(content_block.model_dump())
665+
elif hasattr(content_block, "text"):
666+
content_blocks.append({"type": "text", "text": content_block.text})
667+
668+
_set_output_data(
669+
span=span,
670+
integration=integration,
671+
model=getattr(result, "model", None),
672+
input_tokens=input_tokens,
673+
output_tokens=output_tokens,
674+
cache_read_input_tokens=cache_read_input_tokens,
675+
cache_write_input_tokens=cache_write_input_tokens,
676+
content_blocks=content_blocks,
677+
response_id=getattr(result, "id", None),
678+
finish_reason=getattr(result, "stop_reason", None),
679+
)
680+
span.__exit__(None, None, None)
681+
else:
682+
span.set_data("unknown_response", True)
683+
span.__exit__(None, None, None)
684+
685+
return result
686+
687+
688+
async def _sentry_patched_create_async(
689+
f: "Any", *args: "Any", **kwargs: "Any"
690+
) -> "Any":
691+
"""
692+
Creates and manages an AI Client Span for both non-streaming and streaming calls.
693+
"""
694+
integration = kwargs.pop("integration")
695+
if integration is None:
696+
return await f(*args, **kwargs)
697+
698+
if "messages" not in kwargs:
699+
return await f(*args, **kwargs)
700+
701+
try:
702+
iter(kwargs["messages"])
703+
except TypeError:
704+
return await f(*args, **kwargs)
705+
706+
model = kwargs.get("model", "")
707+
708+
span = get_start_span_function()(
709+
op=OP.GEN_AI_CHAT,
710+
name=f"chat {model}".strip(),
711+
origin=AnthropicIntegration.origin,
712+
)
713+
span.__enter__()
714+
715+
_set_create_input_data(span, kwargs, integration)
716+
717+
try:
718+
result = await f(*args, **kwargs)
719+
except Exception as exc:
720+
exc_info = sys.exc_info()
721+
with capture_internal_exceptions():
722+
_capture_exception(exc)
723+
reraise(*exc_info)
724+
641725
if isinstance(result, AsyncStream):
642726
result._span = span
643727
result._integration = integration
@@ -689,41 +773,20 @@ def _sentry_patched_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "A
689773

690774

691775
def _wrap_message_create(f: "Any") -> "Any":
692-
def _execute_sync(f: "Any", *args: "Any", **kwargs: "Any") -> "Any":
693-
gen = _sentry_patched_create_common(f, *args, **kwargs)
694-
695-
try:
696-
f, args, kwargs = next(gen)
697-
except StopIteration as e:
698-
return e.value
699-
700-
try:
701-
try:
702-
result = f(*args, **kwargs)
703-
except Exception as exc:
704-
exc_info = sys.exc_info()
705-
with capture_internal_exceptions():
706-
_capture_exception(exc)
707-
reraise(*exc_info)
708-
709-
return gen.send(result)
710-
except StopIteration as e:
711-
return e.value
712-
713776
@wraps(f)
714-
def _sentry_patched_create_sync(*args: "Any", **kwargs: "Any") -> "Any":
777+
def _sentry_wrapped_create_sync(*args: "Any", **kwargs: "Any") -> "Any":
715778
integration = sentry_sdk.get_client().get_integration(AnthropicIntegration)
716779
kwargs["integration"] = integration
717780

718781
try:
719-
return _execute_sync(f, *args, **kwargs)
782+
return _sentry_patched_create_sync(f, *args, **kwargs)
720783
finally:
721784
span = sentry_sdk.get_current_span()
722785
if span is not None and span.status == SPANSTATUS.INTERNAL_ERROR:
723786
with capture_internal_exceptions():
724787
span.__exit__(None, None, None)
725788

726-
return _sentry_patched_create_sync
789+
return _sentry_wrapped_create_sync
727790

728791

729792
def _initialize_data_accumulation_state(stream: "Union[Stream, MessageStream]") -> None:
@@ -810,41 +873,20 @@ def close(self: "Union[Stream, MessageStream]") -> None:
810873

811874

812875
def _wrap_message_create_async(f: "Any") -> "Any":
813-
async def _execute_async(f: "Any", *args: "Any", **kwargs: "Any") -> "Any":
814-
gen = _sentry_patched_create_common(f, *args, **kwargs)
815-
816-
try:
817-
f, args, kwargs = next(gen)
818-
except StopIteration as e:
819-
return await e.value
820-
821-
try:
822-
try:
823-
result = await f(*args, **kwargs)
824-
except Exception as exc:
825-
exc_info = sys.exc_info()
826-
with capture_internal_exceptions():
827-
_capture_exception(exc)
828-
reraise(*exc_info)
829-
830-
return gen.send(result)
831-
except StopIteration as e:
832-
return e.value
833-
834876
@wraps(f)
835-
async def _sentry_patched_create_async(*args: "Any", **kwargs: "Any") -> "Any":
877+
async def _sentry_wrapped_create_async(*args: "Any", **kwargs: "Any") -> "Any":
836878
integration = sentry_sdk.get_client().get_integration(AnthropicIntegration)
837879
kwargs["integration"] = integration
838880

839881
try:
840-
return await _execute_async(f, *args, **kwargs)
882+
return await _sentry_patched_create_async(f, *args, **kwargs)
841883
finally:
842884
span = sentry_sdk.get_current_span()
843885
if span is not None and span.status == SPANSTATUS.INTERNAL_ERROR:
844886
with capture_internal_exceptions():
845887
span.__exit__(None, None, None)
846888

847-
return _sentry_patched_create_async
889+
return _sentry_wrapped_create_async
848890

849891

850892
def _wrap_async_close(

0 commit comments

Comments
 (0)