Skip to content

Commit bdcda5e

Browse files
committed
Merge remote-tracking branch 'origin/master' into chore/migrate-to-tox-uv
2 parents f469ce3 + 8a4062b commit bdcda5e

19 files changed

Lines changed: 1208 additions & 383 deletions

File tree

scripts/populate_tox/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@
392392
"deps": {
393393
# https://github.com/jamesls/fakeredis/issues/245
394394
# https://github.com/cunla/fakeredis-py/issues/341
395-
"*": ["fakeredis<2.28.0"],
395+
"*": ["fakeredis"],
396396
"<0.9": ["fakeredis<1.0", "redis<3.2.2"],
397397
">=0.9,<0.14": ["fakeredis>=1.0,<1.7.4"],
398398
"py3.6,py3.7": ["fakeredis!=2.26.0"],

scripts/populate_tox/package_dependencies.jsonl

Lines changed: 41 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/populate_tox/releases.jsonl

Lines changed: 10 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sentry_sdk/integrations/_asgi_common.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,5 @@ def _get_request_attributes(asgi_scope: "Any") -> "dict[str, Any]":
133133
if client and should_send_default_pii():
134134
ip = _get_ip(asgi_scope)
135135
attributes["client.address"] = ip
136-
attributes["user.ip_address"] = ip
137136

138137
return attributes

sentry_sdk/integrations/aiohttp.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,12 @@ async def sentry_app_handle(
165165
else {}
166166
)
167167

168-
client_address_attributes = (
169-
{
170-
"client.address": request.remote,
171-
"user.ip_address": request.remote,
172-
}
173-
if should_send_default_pii() and request.remote
174-
else {}
175-
)
168+
client_address_attributes = {}
169+
if should_send_default_pii() and request.remote:
170+
client_address_attributes["client.address"] = request.remote
171+
scope.set_attribute(
172+
SPANDATA.USER_IP_ADDRESS, request.remote
173+
)
176174

177175
span_ctx = sentry_sdk.traces.start_span(
178176
# If this name makes it to the UI, AIOHTTP's URL

sentry_sdk/integrations/asgi.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212

1313
import sentry_sdk
1414
from sentry_sdk.api import continue_trace
15-
from sentry_sdk.consts import OP
15+
from sentry_sdk.consts import OP, SPANDATA
1616
from sentry_sdk.integrations._asgi_common import (
1717
_get_headers,
18+
_get_ip,
1819
_get_request_attributes,
1920
_get_request_data,
2021
_get_url,
@@ -23,7 +24,7 @@
2324
DEFAULT_HTTP_METHODS_TO_CAPTURE,
2425
nullcontext,
2526
)
26-
from sentry_sdk.scope import Scope
27+
from sentry_sdk.scope import Scope, should_send_default_pii
2728
from sentry_sdk.sessions import track_session
2829
from sentry_sdk.traces import (
2930
SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE,
@@ -247,6 +248,11 @@ async def _run_app(
247248
"network.protocol.name": ty,
248249
}
249250

251+
if scope.get("client") and should_send_default_pii():
252+
sentry_scope.set_attribute(
253+
SPANDATA.USER_IP_ADDRESS, _get_ip(scope)
254+
)
255+
250256
if ty in ("http", "websocket"):
251257
if (
252258
ty == "websocket"

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(

sentry_sdk/integrations/rust_tracing.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@
3232

3333
import json
3434
from enum import Enum, auto
35-
from typing import Any, Callable, Dict, Optional
35+
from typing import Any, Callable, Dict, Optional, Union
3636

3737
import sentry_sdk
3838
from sentry_sdk.integrations import Integration
3939
from sentry_sdk.scope import should_send_default_pii
40+
from sentry_sdk.traces import StreamedSpan
4041
from sentry_sdk.tracing import Span as SentrySpan
42+
from sentry_sdk.tracing_utils import has_span_streaming_enabled
4143
from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE
4244

4345

@@ -182,7 +184,9 @@ def on_event(self, event: str, sentry_span: "SentrySpan") -> None:
182184
elif event_type == EventTypeMapping.Event:
183185
process_event(deserialized_event)
184186

185-
def on_new_span(self, attrs: str, span_id: str) -> "Optional[SentrySpan]":
187+
def on_new_span(
188+
self, attrs: str, span_id: str
189+
) -> "Optional[Union[SentrySpan, StreamedSpan]]":
186190
attrs = json.loads(attrs)
187191
metadata = attrs.get("metadata", {})
188192

@@ -202,13 +206,29 @@ def on_new_span(self, attrs: str, span_id: str) -> "Optional[SentrySpan]":
202206
else:
203207
sentry_span_name = "<unknown>"
204208

205-
kwargs = {
206-
"op": "function",
207-
"name": sentry_span_name,
208-
"origin": self.origin,
209-
}
210-
211-
sentry_span = sentry_sdk.start_span(**kwargs)
209+
span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options)
210+
if span_streaming:
211+
sentry_span = sentry_sdk.traces.start_span(
212+
name=sentry_span_name,
213+
attributes={
214+
"sentry.op": "function",
215+
"sentry.origin": self.origin,
216+
},
217+
)
218+
fields = metadata.get("fields", [])
219+
for field in fields:
220+
if self._include_tracing_fields():
221+
sentry_span.set_attribute(field, attrs.get(field))
222+
else:
223+
sentry_span.set_attribute(field, SENSITIVE_DATA_SUBSTITUTE)
224+
225+
return sentry_span
226+
227+
sentry_span = sentry_sdk.start_span(
228+
op="function",
229+
name=sentry_span_name,
230+
origin=self.origin,
231+
)
212232
fields = metadata.get("fields", [])
213233
for field in fields:
214234
if self._include_tracing_fields():
@@ -225,16 +245,24 @@ def on_close(self, span_id: str, sentry_span: "SentrySpan") -> None:
225245

226246
sentry_span.__exit__(None, None, None)
227247

228-
def on_record(self, span_id: str, values: str, sentry_span: "SentrySpan") -> None:
248+
def on_record(
249+
self, span_id: str, values: str, sentry_span: "Union[SentrySpan, StreamedSpan]"
250+
) -> None:
229251
if sentry_span is None:
230252
return
231253

254+
set_on_span = (
255+
sentry_span.set_attribute
256+
if isinstance(sentry_span, StreamedSpan)
257+
else sentry_span.set_data
258+
)
259+
232260
deserialized_values = json.loads(values)
233261
for key, value in deserialized_values.items():
234262
if self._include_tracing_fields():
235-
sentry_span.set_data(key, value)
263+
set_on_span(key, value)
236264
else:
237-
sentry_span.set_data(key, SENSITIVE_DATA_SUBSTITUTE)
265+
set_on_span(key, SENSITIVE_DATA_SUBSTITUTE)
238266

239267

240268
class RustTracingIntegration(Integration):

sentry_sdk/integrations/sanic.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ async def _context_enter(request: "Request") -> None:
181181
sentry_sdk.traces.continue_trace(dict(request.headers))
182182
scope.set_custom_sampling_context({"sanic_request": request})
183183

184+
if should_send_default_pii() and request.remote_addr:
185+
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr)
186+
184187
span = sentry_sdk.traces.start_span(
185188
# Unless the request results in a 404 error, the name and source
186189
# will get overwritten in _set_transaction
@@ -375,7 +378,6 @@ def _get_request_attributes(request: "Request") -> "Dict[str, Any]":
375378

376379
if should_send_default_pii() and request.remote_addr:
377380
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_addr
378-
attributes[SPANDATA.USER_IP_ADDRESS] = request.remote_addr
379381

380382
return attributes
381383

sentry_sdk/integrations/tornado.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
130130
sentry_sdk.traces.continue_trace(dict(headers))
131131
scope.set_custom_sampling_context({"tornado_request": self.request})
132132

133+
if should_send_default_pii() and self.request.remote_ip:
134+
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, self.request.remote_ip)
135+
133136
span_ctx = sentry_sdk.traces.start_span(
134137
name=_DEFAULT_ROOT_SPAN_NAME,
135138
attributes={
@@ -204,7 +207,6 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
204207

205208
if should_send_default_pii() and request.remote_ip:
206209
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip
207-
attributes[SPANDATA.USER_IP_ADDRESS] = request.remote_ip
208210

209211
with capture_internal_exceptions():
210212
raw_data = _get_tornado_request_data(request)

0 commit comments

Comments
 (0)