Skip to content

Commit 0749d3e

Browse files
feat(litellm): Support span streaming (#6317)
1 parent b4e0367 commit 0749d3e

2 files changed

Lines changed: 282 additions & 43 deletions

File tree

sentry_sdk/integrations/litellm.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
from sentry_sdk.consts import SPANDATA
1515
from sentry_sdk.integrations import DidNotEnable, Integration
1616
from sentry_sdk.scope import should_send_default_pii
17+
from sentry_sdk.tracing_utils import (
18+
has_span_streaming_enabled,
19+
should_truncate_gen_ai_input,
20+
)
1721
from sentry_sdk.utils import event_from_exception
1822

1923
if TYPE_CHECKING:
@@ -68,7 +72,8 @@ def _convert_message_parts(messages: "List[Dict[str, Any]]") -> "List[Dict[str,
6872

6973
def _input_callback(kwargs: "Dict[str, Any]") -> None:
7074
"""Handle the start of a request."""
71-
integration = sentry_sdk.get_client().get_integration(LiteLLMIntegration)
75+
client = sentry_sdk.get_client()
76+
integration = client.get_integration(LiteLLMIntegration)
7277

7378
if integration is None:
7479
return
@@ -88,16 +93,29 @@ def _input_callback(kwargs: "Dict[str, Any]") -> None:
8893
operation = "chat"
8994

9095
# Start a new span/transaction
91-
span = get_start_span_function()(
92-
op=(
93-
consts.OP.GEN_AI_CHAT
94-
if operation == "chat"
95-
else consts.OP.GEN_AI_EMBEDDINGS
96-
),
97-
name=f"{operation} {model}",
98-
origin=LiteLLMIntegration.origin,
99-
)
100-
span.__enter__()
96+
if has_span_streaming_enabled(client.options):
97+
span = sentry_sdk.traces.start_span(
98+
name=f"{operation} {model}",
99+
attributes={
100+
"sentry.op": (
101+
consts.OP.GEN_AI_CHAT
102+
if operation == "chat"
103+
else consts.OP.GEN_AI_EMBEDDINGS
104+
),
105+
"sentry.origin": LiteLLMIntegration.origin,
106+
},
107+
)
108+
else:
109+
span = get_start_span_function()(
110+
op=(
111+
consts.OP.GEN_AI_CHAT
112+
if operation == "chat"
113+
else consts.OP.GEN_AI_EMBEDDINGS
114+
),
115+
name=f"{operation} {model}",
116+
origin=LiteLLMIntegration.origin,
117+
)
118+
span.__enter__()
101119

102120
# Store span for later
103121
_get_metadata_dict(kwargs)["_sentry_span"] = span
@@ -121,9 +139,9 @@ def _input_callback(kwargs: "Dict[str, Any]") -> None:
121139
)
122140
client = sentry_sdk.get_client()
123141
messages_data = (
124-
input_list
125-
if client.options.get("stream_gen_ai_spans", False)
126-
else truncate_and_annotate_embedding_inputs(input_list, span, scope)
142+
truncate_and_annotate_embedding_inputs(input_list, span, scope)
143+
if should_truncate_gen_ai_input(client.options)
144+
else input_list
127145
)
128146
if messages_data is not None:
129147
set_data_normalized(
@@ -140,9 +158,9 @@ def _input_callback(kwargs: "Dict[str, Any]") -> None:
140158
scope = sentry_sdk.get_current_scope()
141159
messages = _convert_message_parts(messages)
142160
messages_data = (
143-
messages
144-
if client.options.get("stream_gen_ai_spans", False)
145-
else truncate_and_annotate_messages(messages, span, scope)
161+
truncate_and_annotate_messages(messages, span, scope)
162+
if should_truncate_gen_ai_input(client.options)
163+
else messages
146164
)
147165
if messages_data is not None:
148166
set_data_normalized(

0 commit comments

Comments
 (0)