-
Notifications
You must be signed in to change notification settings - Fork 639
fix(tracing): Skip child span creation in streaming path when no current span (AI agents) #6813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,15 +31,17 @@ | |
| model_name = agent._sentry_request_model | ||
|
|
||
| span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) | ||
| if span_streaming: | ||
| span = sentry_sdk.traces.start_span( | ||
| name=f"chat {model_name}", | ||
| attributes={ | ||
| "sentry.op": OP.GEN_AI_CHAT, | ||
| "sentry.origin": SPAN_ORIGIN, | ||
| SPANDATA.GEN_AI_OPERATION_NAME: "chat", | ||
| }, | ||
| ) | ||
| span = None | ||
| if sentry_sdk.traces.get_current_span() is not None: | ||
| span = sentry_sdk.traces.start_span( | ||
| name=f"chat {model_name}", | ||
| attributes={ | ||
| "sentry.op": OP.GEN_AI_CHAT, | ||
| "sentry.origin": SPAN_ORIGIN, | ||
| SPANDATA.GEN_AI_OPERATION_NAME: "chat", | ||
| }, | ||
| ) | ||
|
Check failure on line 44 in sentry_sdk/integrations/openai_agents/spans/ai_client.py
|
||
|
Comment on lines
34
to
+44
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ai_client_span can return None, breaking In streaming mode with no current span, Evidence
Also found at 3 additional locations
Identified by Warden code-review · P4J-HWE |
||
| else: | ||
| span = sentry_sdk.start_span( | ||
| op=OP.GEN_AI_CHAT, | ||
|
|
@@ -49,10 +51,11 @@ | |
| # TODO-anton: remove hardcoded stuff and replace something that also works for embedding and so on | ||
| span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") | ||
|
|
||
| _set_agent_data(span, agent) | ||
| _set_input_data(span, get_response_kwargs) | ||
| if span is not None: | ||
| _set_agent_data(span, agent) | ||
| _set_input_data(span, get_response_kwargs) | ||
|
|
||
| return span | ||
|
Check failure on line 58 in sentry_sdk/integrations/openai_agents/spans/ai_client.py
|
||
|
|
||
|
|
||
| def update_ai_client_span( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -281,39 +281,42 @@ | |
| model_name = _get_model_name(model_obj) or "unknown" | ||
|
|
||
| span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) | ||
| if span_streaming: | ||
| span = sentry_sdk.traces.start_span( | ||
| name=f"chat {model_name}", | ||
| attributes={ | ||
| "sentry.op": OP.GEN_AI_CHAT, | ||
| "sentry.origin": SPAN_ORIGIN, | ||
| SPANDATA.GEN_AI_OPERATION_NAME: "chat", | ||
| SPANDATA.GEN_AI_RESPONSE_STREAMING: get_is_streaming(), | ||
| }, | ||
| ) | ||
| span = None | ||
| if sentry_sdk.traces.get_current_span() is not None: | ||
| span = sentry_sdk.traces.start_span( | ||
| name=f"chat {model_name}", | ||
| attributes={ | ||
| "sentry.op": OP.GEN_AI_CHAT, | ||
| "sentry.origin": SPAN_ORIGIN, | ||
| SPANDATA.GEN_AI_OPERATION_NAME: "chat", | ||
| SPANDATA.GEN_AI_RESPONSE_STREAMING: get_is_streaming(), | ||
| }, | ||
| ) | ||
| else: | ||
| span = sentry_sdk.start_span( | ||
| op=OP.GEN_AI_CHAT, | ||
| name=f"chat {model_name}", | ||
| origin=SPAN_ORIGIN, | ||
| ) | ||
|
|
||
| span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") | ||
| # Set streaming flag from contextvar | ||
| span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, get_is_streaming()) | ||
|
|
||
| _set_agent_data(span, agent) | ||
| _set_model_data(span, model, model_settings) | ||
| if span is not None: | ||
| _set_agent_data(span, agent) | ||
| _set_model_data(span, model, model_settings) | ||
|
|
||
| # Add available tools if agent is available | ||
| agent_obj = agent or get_current_agent() | ||
| _set_available_tools(span, agent_obj) | ||
| # Add available tools if agent is available | ||
| agent_obj = agent or get_current_agent() | ||
| _set_available_tools(span, agent_obj) | ||
|
|
||
| # Set input messages (full conversation history) | ||
| if messages: | ||
| _set_input_messages(span, messages) | ||
| # Set input messages (full conversation history) | ||
| if messages: | ||
| _set_input_messages(span, messages) | ||
|
Check failure on line 317 in sentry_sdk/integrations/pydantic_ai/spans/ai_client.py
|
||
|
Comment on lines
284
to
+317
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ai_client_span can return None but callers use it as a context manager When streaming is enabled and there is no current span, Evidence
Also found at 2 additional locations
Identified by Warden code-review · MGK-CD6 |
||
|
|
||
| return span | ||
|
Check failure on line 319 in sentry_sdk/integrations/pydantic_ai/spans/ai_client.py
|
||
|
|
||
|
|
||
| def update_ai_client_span( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agent_workflow_span can return None, crashing both callers
In streaming mode with no current span this returns None, but callers do
with agent_workflow_span(agent) as workflow_span:andworkflow_span.__enter__(), both of which raise AttributeError on None.Evidence
span = Noneand only assigns a real span whenget_current_span() is not None, soreturn spancan return None.runner.py:45useswith agent_workflow_span(agent) as workflow_span:; entering awith Noneblock raisesAttributeError: __enter__.runner.py:156-157doesworkflow_span = agent_workflow_span(agent)thenworkflow_span.__enter__(), dereferencing None with no guard.Also found at 6 additional locations
sentry_sdk/integrations/openai_agents/spans/ai_client.py:58sentry_sdk/integrations/openai_agents/spans/invoke_agent.py:33-41sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py:72sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py:53-63sentry_sdk/integrations/pydantic_ai/spans/ai_client.py:319sentry_sdk/integrations/openai_agents/spans/execute_tool.py:22-22Identified by Warden find-bugs · WP8-UZK