Skip to content

Commit 7cf1dc8

Browse files
add error hook
1 parent 9a02158 commit 7cf1dc8

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

sentry_sdk/integrations/pydantic_ai/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ def setup_once() -> None:
6262
from pydantic_ai.capabilities import Hooks # type: ignore
6363
except ImportError:
6464
Hooks = None
65-
# Save to populate ctx.metadata
6665
PydanticAIIntegration.are_request_hooks_available = True
6766

6867
if Hooks is None:
@@ -72,6 +71,9 @@ def setup_once() -> None:
7271

7372
_patch_tool_execution()
7473

74+
# Assumptions:
75+
# - Model requests within a run are sequential.
76+
# - ctx.metadata is a shared dict instance between hooks.
7577
hooks = Hooks()
7678

7779
@hooks.on.before_model_request # type: ignore
@@ -113,6 +115,20 @@ async def on_response(
113115

114116
return response
115117

118+
@hooks.on.model_request_error # type: ignore
119+
async def on_error(
120+
ctx: "RunContext[None]",
121+
*,
122+
request_context: "ModelRequestContext",
123+
error: "Exception",
124+
) -> "ModelResponse":
125+
run_context_metadata = ctx.metadata
126+
if isinstance(run_context_metadata, dict):
127+
span = run_context_metadata.pop("_sentry_span", None)
128+
if span is not None:
129+
span.__exit__(type(error), error, error.__traceback__)
130+
raise error
131+
116132
original_init = Agent.__init__
117133

118134
@functools.wraps(original_init)

sentry_sdk/integrations/pydantic_ai/patches/agent_run.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ def _create_run_wrapper(
9696
original_func: The original run method
9797
is_streaming: Whether this is a streaming method (for future use)
9898
"""
99-
from sentry_sdk.integrations.pydantic_ai import PydanticAIIntegration
99+
from sentry_sdk.integrations.pydantic_ai import (
100+
PydanticAIIntegration,
101+
) # Required to avoid circular import
100102

101103
@wraps(original_func)
102104
async def wrapper(self: "Any", *args: "Any", **kwargs: "Any") -> "Any":
@@ -146,7 +148,9 @@ def _create_streaming_wrapper(
146148
"""
147149
Wraps run_stream method that returns an async context manager.
148150
"""
149-
from sentry_sdk.integrations.pydantic_ai import PydanticAIIntegration
151+
from sentry_sdk.integrations.pydantic_ai import (
152+
PydanticAIIntegration,
153+
) # Required to avoid circular import
150154

151155
@wraps(original_func)
152156
def wrapper(self: "Any", *args: "Any", **kwargs: "Any") -> "Any":

0 commit comments

Comments
 (0)