Skip to content

Commit 73e2b7e

Browse files
feat(ai): Create transaction in AI agents framworks, when no transaction is running. (#4758)
This includes: - nthropic: `message.create` - langchain: `invoke_agent` spans - openai_agent: `invoke_agent` spans + agent workflow (which was already like that) Closes https://linear.app/getsentry/issue/TET-1048/auto-wrap-gen-aiinvoke-agent-if-no-transaction-in-scope Co-authored-by: Anton Pirker <[email protected]>
1 parent 18d3899 commit 73e2b7e

File tree

6 files changed

+23
-20
lines changed

6 files changed

+23
-20
lines changed

sentry_sdk/ai/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
from typing import TYPE_CHECKING
44

55
if TYPE_CHECKING:
6-
from typing import Any
6+
from typing import Any, Callable
77
from sentry_sdk.tracing import Span
88

9+
import sentry_sdk
910
from sentry_sdk.utils import logger
1011

1112

@@ -37,3 +38,12 @@ def set_data_normalized(span, key, value, unpack=True):
3738
span.set_data(key, normalized)
3839
else:
3940
span.set_data(key, json.dumps(normalized))
41+
42+
43+
def get_start_span_function():
44+
# type: () -> Callable[..., Any]
45+
current_span = sentry_sdk.get_current_span()
46+
transaction_exists = (
47+
current_span is not None and current_span.containing_transaction == current_span
48+
)
49+
return sentry_sdk.start_span if transaction_exists else sentry_sdk.start_transaction

sentry_sdk/integrations/anthropic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import sentry_sdk
66
from sentry_sdk.ai.monitoring import record_token_usage
7-
from sentry_sdk.ai.utils import set_data_normalized
7+
from sentry_sdk.ai.utils import set_data_normalized, get_start_span_function
88
from sentry_sdk.consts import OP, SPANDATA
99
from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration
1010
from sentry_sdk.scope import should_send_default_pii
@@ -194,7 +194,7 @@ def _sentry_patched_create_common(f, *args, **kwargs):
194194

195195
model = kwargs.get("model", "")
196196

197-
span = sentry_sdk.start_span(
197+
span = get_start_span_function()(
198198
op=OP.GEN_AI_CHAT,
199199
name=f"chat {model}".strip(),
200200
origin=AnthropicIntegration.origin,

sentry_sdk/integrations/langchain.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import sentry_sdk
66
from sentry_sdk.ai.monitoring import set_ai_pipeline_name
7-
from sentry_sdk.ai.utils import set_data_normalized
7+
from sentry_sdk.ai.utils import set_data_normalized, get_start_span_function
88
from sentry_sdk.consts import OP, SPANDATA
99
from sentry_sdk.integrations import DidNotEnable, Integration
1010
from sentry_sdk.scope import should_send_default_pii
@@ -716,8 +716,9 @@ def new_invoke(self, *args, **kwargs):
716716
return f(self, *args, **kwargs)
717717

718718
agent_name, tools = _get_request_data(self, args, kwargs)
719+
start_span_function = get_start_span_function()
719720

720-
with sentry_sdk.start_span(
721+
with start_span_function(
721722
op=OP.GEN_AI_INVOKE_AGENT,
722723
name=f"invoke_agent {agent_name}" if agent_name else "invoke_agent",
723724
origin=LangchainIntegration.origin,
@@ -767,8 +768,9 @@ def new_stream(self, *args, **kwargs):
767768
return f(self, *args, **kwargs)
768769

769770
agent_name, tools = _get_request_data(self, args, kwargs)
771+
start_span_function = get_start_span_function()
770772

771-
span = sentry_sdk.start_span(
773+
span = start_span_function(
772774
op=OP.GEN_AI_INVOKE_AGENT,
773775
name=f"invoke_agent {agent_name}".strip(),
774776
origin=LangchainIntegration.origin,

sentry_sdk/integrations/openai_agents/spans/agent_workflow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sentry_sdk
2+
from sentry_sdk.ai.utils import get_start_span_function
23

34
from ..consts import SPAN_ORIGIN
4-
from ..utils import _get_start_span_function
55

66
from typing import TYPE_CHECKING
77

@@ -13,7 +13,7 @@ def agent_workflow_span(agent):
1313
# type: (agents.Agent) -> sentry_sdk.tracing.Span
1414

1515
# Create a transaction or a span if an transaction is already active
16-
span = _get_start_span_function()(
16+
span = get_start_span_function()(
1717
name=f"{agent.name} workflow",
1818
origin=SPAN_ORIGIN,
1919
)

sentry_sdk/integrations/openai_agents/spans/invoke_agent.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import sentry_sdk
2-
from sentry_sdk.ai.utils import set_data_normalized
2+
from sentry_sdk.ai.utils import get_start_span_function, set_data_normalized
33
from sentry_sdk.consts import OP, SPANDATA
44
from sentry_sdk.scope import should_send_default_pii
55
from sentry_sdk.utils import safe_serialize
@@ -16,7 +16,8 @@
1616

1717
def invoke_agent_span(context, agent, kwargs):
1818
# type: (agents.RunContextWrapper, agents.Agent, dict[str, Any]) -> sentry_sdk.tracing.Span
19-
span = sentry_sdk.start_span(
19+
start_span_function = get_start_span_function()
20+
span = start_span_function(
2021
op=OP.GEN_AI_INVOKE_AGENT,
2122
name=f"invoke_agent {agent.name}",
2223
origin=SPAN_ORIGIN,

sentry_sdk/integrations/openai_agents/utils.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
if TYPE_CHECKING:
1111
from typing import Any
12-
from typing import Callable
1312
from agents import Usage
1413

1514
try:
@@ -29,15 +28,6 @@ def _capture_exception(exc):
2928
sentry_sdk.capture_event(event, hint=hint)
3029

3130

32-
def _get_start_span_function():
33-
# type: () -> Callable[..., Any]
34-
current_span = sentry_sdk.get_current_span()
35-
transaction_exists = (
36-
current_span is not None and current_span.containing_transaction == current_span
37-
)
38-
return sentry_sdk.start_span if transaction_exists else sentry_sdk.start_transaction
39-
40-
4131
def _set_agent_data(span, agent):
4232
# type: (sentry_sdk.tracing.Span, agents.Agent) -> None
4333
span.set_data(

0 commit comments

Comments
 (0)