Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sentry_sdk/integrations/google_genai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def new_generate_content_stream(self, *args, **kwargs):
chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name)
set_span_data_for_request(chat_span, integration, model_name, contents, kwargs)
chat_span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True)
chat_span.set_data(SPANDATA.GEN_AI_AGENT_NAME, model_name)

try:
stream = f(self, *args, **kwargs)
Expand Down Expand Up @@ -165,6 +166,7 @@ async def new_async_generate_content_stream(self, *args, **kwargs):
chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name)
set_span_data_for_request(chat_span, integration, model_name, contents, kwargs)
chat_span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True)
chat_span.set_data(SPANDATA.GEN_AI_AGENT_NAME, model_name)

try:
stream = await f(self, *args, **kwargs)
Expand Down Expand Up @@ -233,6 +235,7 @@ def new_generate_content(self, *args, **kwargs):
chat_span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat")
chat_span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM)
chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name)
chat_span.set_data(SPANDATA.GEN_AI_AGENT_NAME, model_name)
set_span_data_for_request(
chat_span, integration, model_name, contents, kwargs
)
Expand Down
31 changes: 30 additions & 1 deletion sentry_sdk/integrations/langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ def on_chat_model_start(self, serialized, messages, *, run_id, **kwargs):
elif "openai" in ai_type:
span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai")

agent_name = (
sentry_sdk.get_current_scope()
._contexts.get("langchain_agent", {})
.get("agent_name")
)
if agent_name:
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)

for key, attribute in DATA_FIELDS.items():
if key in all_params and all_params[key] is not None:
set_data_normalized(span, attribute, all_params[key], unpack=False)
Expand Down Expand Up @@ -428,6 +436,14 @@ def on_tool_start(self, serialized, input_str, *, run_id, **kwargs):
if tool_description is not None:
span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_description)

agent_name = (
sentry_sdk.get_current_scope()
._contexts.get("langchain_agent", {})
.get("agent_name")
)
if agent_name:
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)

if should_send_default_pii() and self.include_prompts:
set_data_normalized(
span,
Expand Down Expand Up @@ -756,6 +772,9 @@ def new_invoke(self, *args, **kwargs):
name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent",
origin=LangchainIntegration.origin,
) as span:
sentry_sdk.get_current_scope().set_context(
"langchain_agent", {"agent_name": agent_name, "tools": tools}
)
if agent_name:
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)

Expand Down Expand Up @@ -794,6 +813,8 @@ def new_invoke(self, *args, **kwargs):
):
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)

sentry_sdk.get_current_scope().remove_context("langchain_agent")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Context Leak in Exception Handling

Context leak in _wrap_agent_executor_invoke: if f(self, *args, **kwargs) throws an exception after the context is set (line 775-777), the remove_context call at line 816 will never execute, causing the "langchain_agent" context to persist beyond its intended scope.

Fix in Cursor Fix in Web


return result

return new_invoke
Expand All @@ -814,11 +835,15 @@ def new_stream(self, *args, **kwargs):

span = start_span_function(
op=OP.GEN_AI_INVOKE_AGENT,
name=f"invoke_agent {agent_name}".strip(),
name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent",
origin=LangchainIntegration.origin,
)
span.__enter__()

sentry_sdk.get_current_scope().set_context(
"langchain_agent", {"agent_name": agent_name, "tools": tools}
)

if agent_name:
span.set_data(SPANDATA.GEN_AI_AGENT_NAME, agent_name)

Expand Down Expand Up @@ -868,6 +893,8 @@ def new_iterator():
):
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)

sentry_sdk.get_current_scope().remove_context("langchain_agent")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Context Leak in Exception Handling

Context leak in _wrap_agent_executor_stream: if f(self, *args, **kwargs) throws an exception after the context is set (line 843-845), the iterators containing the remove_context calls (lines 896, 917) are never created, causing the "langchain_agent" context to leak permanently.

Fix in Cursor Fix in Web


span.__exit__(None, None, None)

async def new_iterator_async():
Expand All @@ -887,6 +914,8 @@ async def new_iterator_async():
):
set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output)

sentry_sdk.get_current_scope().remove_context("langchain_agent")

span.__exit__(None, None, None)

if str(type(result)) == "<class 'async_generator'>":
Expand Down