Skip to content

Commit 2c0edd5

Browse files
fix(openai-agents): Avoid double span exit on exception
1 parent 4ca61e6 commit 2c0edd5

File tree

3 files changed

+46
-22
lines changed

3 files changed

+46
-22
lines changed

sentry_sdk/integrations/openai_agents/patches/agent_run.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
from functools import wraps
22

33
from sentry_sdk.integrations import DidNotEnable
4+
from sentry_sdk.tracing_utils import set_span_errored
45
from ..spans import invoke_agent_span, update_invoke_agent_span, handoff_span
6+
from ..utils import _capture_exception, _record_exception_on_span
57

68
from typing import TYPE_CHECKING
79

810
if TYPE_CHECKING:
911
from typing import Any, Optional
1012

13+
from sentry_sdk.tracing import Span
14+
1115
try:
1216
import agents
1317
except ImportError:
@@ -27,13 +31,15 @@ def _patch_agent_run():
2731
original_execute_final_output = agents._run_impl.RunImpl.execute_final_output
2832

2933
def _start_invoke_agent_span(context_wrapper, agent, kwargs):
30-
# type: (agents.RunContextWrapper, agents.Agent, dict[str, Any]) -> None
34+
# type: (agents.RunContextWrapper, agents.Agent, dict[str, Any]) -> Span
3135
"""Start an agent invocation span"""
3236
# Store the agent on the context wrapper so we can access it later
3337
context_wrapper._sentry_current_agent = agent
3438
span = invoke_agent_span(context_wrapper, agent, kwargs)
3539
context_wrapper._sentry_agent_span = span
3640

41+
return span
42+
3743
def _end_invoke_agent_span(context_wrapper, agent, output=None):
3844
# type: (agents.RunContextWrapper, agents.Agent, Optional[Any]) -> None
3945
"""End the agent invocation span"""
@@ -65,18 +71,21 @@ async def patched_run_single_turn(cls, *args, **kwargs):
6571
context_wrapper = kwargs.get("context_wrapper")
6672
should_run_agent_start_hooks = kwargs.get("should_run_agent_start_hooks")
6773

74+
span = getattr(context_wrapper, "_sentry_current_agent", None)
6875
# Start agent span when agent starts (but only once per agent)
6976
if should_run_agent_start_hooks and agent and context_wrapper:
70-
# End any existing span for a different agent
71-
if _has_active_agent_span(context_wrapper):
72-
current_agent = _get_current_agent(context_wrapper)
73-
if current_agent and current_agent != agent:
74-
_end_invoke_agent_span(context_wrapper, current_agent)
75-
76-
_start_invoke_agent_span(context_wrapper, agent, kwargs)
77+
span = _start_invoke_agent_span(context_wrapper, agent, kwargs)
7778

7879
# Call original method with all the correct parameters
79-
result = await original_run_single_turn(*args, **kwargs)
80+
try:
81+
result = await original_run_single_turn(*args, **kwargs)
82+
except Exception as exc:
83+
if span is not None and span.timestamp is None:
84+
_record_exception_on_span(span, exc)
85+
span.__exit__(None, None, None)
86+
87+
_capture_exception(exc)
88+
raise exc from None
8089

8190
return result
8291

sentry_sdk/integrations/openai_agents/patches/runner.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ async def wrapper(*args, **kwargs):
2828
with sentry_sdk.isolation_scope():
2929
agent = args[0]
3030
with agent_workflow_span(agent):
31-
result = None
32-
try:
33-
result = await original_func(*args, **kwargs)
34-
return result
35-
except Exception as exc:
36-
_capture_exception(exc)
37-
38-
# It could be that there is a "invoke agent" span still open
39-
current_span = sentry_sdk.get_current_span()
40-
if current_span is not None and current_span.timestamp is None:
41-
current_span.__exit__(None, None, None)
42-
43-
raise exc from None
31+
run_result = await original_func(*args, **kwargs)
32+
33+
invoke_agent_span = getattr(
34+
run_result.context_wrapper, "_sentry_agent_span", None
35+
)
36+
37+
if (
38+
invoke_agent_span is not None
39+
and invoke_agent_span.timestamp is None
40+
):
41+
invoke_agent_span.__exit__(None, None, None)
42+
43+
return run_result
4444

4545
return wrapper

sentry_sdk/integrations/openai_agents/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ def _capture_exception(exc):
3636
sentry_sdk.capture_event(event, hint=hint)
3737

3838

39+
def _record_exception_on_span(span, error):
40+
# type: (Optional[Span], Exception) -> Any
41+
if span is not None:
42+
set_span_errored(span)
43+
span.set_data("span.status", "error")
44+
45+
# Optionally capture the error details if we have them
46+
if hasattr(error, "__class__"):
47+
span.set_data("error.type", error.__class__.__name__)
48+
if hasattr(error, "__str__"):
49+
error_message = str(error)
50+
if error_message:
51+
span.set_data("error.message", error_message)
52+
53+
3954
def _set_agent_data(span, agent):
4055
# type: (sentry_sdk.tracing.Span, agents.Agent) -> None
4156
span.set_data(

0 commit comments

Comments
 (0)