Skip to content

Commit 03f7e24

Browse files
committed
Creating some spans
1 parent 09425e6 commit 03f7e24

File tree

2 files changed

+164
-17
lines changed

2 files changed

+164
-17
lines changed
Lines changed: 160 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,179 @@
1+
import sys
2+
13
import sentry_sdk
24
from sentry_sdk.integrations import DidNotEnable, Integration
35
from sentry_sdk.utils import event_from_exception
46

5-
from typing import TYPE_CHECKING
6-
7-
if TYPE_CHECKING:
8-
from typing import Any
7+
from typing import Any
98

109
try:
11-
from agents import Agent # noqa: F401
10+
import agents
11+
from agents import (
12+
Agent,
13+
RunContextWrapper,
14+
RunHooks,
15+
Tool,
16+
Usage,
17+
)
18+
from agents.tracing.setup import TraceProvider
19+
from agents.tracing.spans import Span, TSpanData
20+
from agents.tracing.traces import Trace
21+
1222
except ImportError:
1323
raise DidNotEnable("OpenAI Agents not installed")
1424

1525

26+
def _capture_exception(exc):
27+
# type: (Any) -> None
28+
event, hint = event_from_exception(
29+
exc,
30+
client_options=sentry_sdk.get_client().options,
31+
mechanism={"type": OpenAIAgentsIntegration.identifier, "handled": False},
32+
)
33+
sentry_sdk.capture_event(event, hint=hint)
34+
35+
36+
class SentryTraceProvider:
37+
def __init__(self, original: TraceProvider):
38+
self.original = original
39+
40+
def create_trace(
41+
self,
42+
name: str,
43+
trace_id: str | None = None,
44+
disabled: bool = False,
45+
**kwargs: Any,
46+
) -> Trace:
47+
print(f"[SentryTraceProvider] create_trace: {name}")
48+
trace = self.original.create_trace(
49+
name, trace_id=trace_id, disabled=disabled, **kwargs
50+
)
51+
return trace
52+
53+
def create_span(
54+
self,
55+
span_data: TSpanData,
56+
span_id: str | None = None,
57+
parent: Trace | Span[Any] | None = None,
58+
disabled: bool = False,
59+
) -> Span[TSpanData]:
60+
print(f"[SentryTraceProvider] create_span: {span_data}")
61+
span = self.original.create_span(span_data, span_id, parent, disabled)
62+
63+
# current_span = Scope.get_current_span()
64+
# current_trace = Scope.get_current_trace()
65+
66+
# sentry_span = sentry_sdk.start_span(
67+
# op=AGENTS_TO_OP[span_data.__class__.__name__],
68+
# name=AGENTS_TO_NAME[span_data.__class__.__name__],
69+
# attributes=span_data.export()
70+
# )
71+
# sentry_span.finish()
72+
return span
73+
74+
def __getattr__(self, item: Any) -> Any:
75+
return getattr(self.original, item)
76+
77+
78+
class SentryRunHooks(RunHooks):
79+
def __init__(self):
80+
self.event_counter = 0
81+
82+
def _usage_to_str(self, usage: Usage) -> str:
83+
return f"{usage.requests} requests, {usage.input_tokens} input tokens, {usage.output_tokens} output tokens, {usage.total_tokens} total tokens"
84+
85+
async def on_agent_start(self, context: RunContextWrapper, agent: Agent) -> None:
86+
self.event_counter += 1
87+
print(
88+
f"### {self.event_counter}: Agent {agent.name} started. Usage: {self._usage_to_str(context.usage)}"
89+
)
90+
span = sentry_sdk.start_span(op="gen_ai.agent_start", description=agent.name)
91+
span.__enter__()
92+
self.agent_span = span
93+
94+
async def on_agent_end(
95+
self, context: RunContextWrapper, agent: Agent, output: Any
96+
) -> None:
97+
self.event_counter += 1
98+
print(
99+
f"### {self.event_counter}: Agent '{agent.name}' ended with output {output}. Usage: {self._usage_to_str(context.usage)}"
100+
)
101+
print(self.agent_span)
102+
if self.agent_span:
103+
print(f"Span exit agent: {self.agent_span}")
104+
self.agent_span.__exit__(None, None, None)
105+
self.agent_span = None
106+
107+
async def on_tool_start(
108+
self, context: RunContextWrapper, agent: Agent, tool: Tool
109+
) -> None:
110+
self.event_counter += 1
111+
print(
112+
f"### {self.event_counter}: Tool {tool.name} started. Usage: {self._usage_to_str(context.usage)}"
113+
)
114+
span = sentry_sdk.start_span(op="gen_ai.tool_start", description=tool.name)
115+
span.__enter__()
116+
self.tool_span = span
117+
118+
async def on_tool_end(
119+
self, context: RunContextWrapper, agent: Agent, tool: Tool, result: str
120+
) -> None:
121+
self.event_counter += 1
122+
print(
123+
f"### {self.event_counter}: Tool {tool.name} ended with result {result}. Usage: {self._usage_to_str(context.usage)}"
124+
)
125+
if self.tool_span:
126+
print(f"Span exit tool: {self.tool_span}")
127+
self.tool_span.__exit__(None, None, None)
128+
self.tool_span = None
129+
130+
async def on_handoff(
131+
self, context: RunContextWrapper, from_agent: Agent, to_agent: Agent
132+
) -> None:
133+
self.event_counter += 1
134+
print(
135+
f"### {self.event_counter}: Handoff from '{from_agent.name}' to '{to_agent.name}'. Usage: {self._usage_to_str(context.usage)}"
136+
)
137+
if self.agent_span:
138+
span = self.agent_span.start_child(
139+
op="gen_ai.handoff", description=f"{from_agent.name} -> {to_agent.name}"
140+
)
141+
print(f"Span enter handoff: {span}")
142+
span.__enter__()
143+
print(f"Span exit handoff: {span}")
144+
span.__exit__(None, None, None)
145+
146+
print(f"Span exit agent: {self.agent_span}")
147+
self.agent_span.__exit__(None, None, None)
148+
self.agent_span = None
149+
150+
151+
def _patch_tracer_provider():
152+
# Monkey path trace provider of openai-agents
153+
name = "GLOBAL_TRACE_PROVIDER"
154+
original = getattr(agents.tracing, name)
155+
already_wrapped = isinstance(original, SentryTraceProvider)
156+
if not already_wrapped:
157+
wrapper = SentryTraceProvider(original)
158+
for module_name, mod in sys.modules.items():
159+
if module_name.startswith("agents"):
160+
try:
161+
if getattr(mod, name, None) is original:
162+
setattr(mod, name, wrapper)
163+
except Exception: # pragma: no cover
164+
pass
165+
166+
16167
class OpenAIAgentsIntegration(Integration):
17168
identifier = "openai_agents"
18169
origin = f"auto.ai.{identifier}"
19170

20-
def __init__(self):
21-
pass
171+
# def __init__(self):
172+
# pass
22173

23174
@staticmethod
24175
def setup_once():
25176
# type: () -> None
26-
pass
27-
177+
# _patch_tracer_provider()
28178

29-
def _capture_exception(exc):
30-
# type: (Any) -> None
31-
event, hint = event_from_exception(
32-
exc,
33-
client_options=sentry_sdk.get_client().options,
34-
mechanism={"type": OpenAIAgentsIntegration.identifier, "handled": False},
35-
)
36-
sentry_sdk.capture_event(event, hint=hint)
179+
pass

tests/integrations/openai_agents/test_openai_agents.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@
44
def test_basic(sentry_init):
55
sentry_init(integrations=[OpenAIAgentsIntegration()])
66

7+
import ipdb
8+
9+
ipdb.set_trace()
10+
711
assert True

0 commit comments

Comments
 (0)