Skip to content
Merged
24 changes: 18 additions & 6 deletions sentry_sdk/integrations/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ async def sentry_app_handle(
)

url_attributes = {}
client_address_attributes = {}

if has_data_collection_enabled(client.options):
url_attributes["url.full"] = "%s://%s%s" % (
request.scheme,
Expand All @@ -188,6 +190,15 @@ async def sentry_app_handle(
"?" + filtered_query_string
)

if request.remote:
if client.options["data_collection"]["user_info"]:
client_address_attributes["client.address"] = (
request.remote
)
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, request.remote
)

elif should_send_default_pii():
url_full = "%s://%s%s" % (
request.scheme,
Expand All @@ -201,12 +212,13 @@ async def sentry_app_handle(
url_attributes["url.full"] = url_full
url_attributes["url.path"] = request.path

client_address_attributes = {}
if should_send_default_pii() and request.remote:
client_address_attributes["client.address"] = request.remote
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, request.remote
)
if request.remote:
client_address_attributes["client.address"] = (
request.remote
)
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, request.remote
)

span_ctx = sentry_sdk.traces.start_span(
# If this name makes it to the UI, AIOHTTP's URL
Expand Down
78 changes: 46 additions & 32 deletions sentry_sdk/integrations/django/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
capture_internal_exceptions,
ensure_integration_enabled,
event_from_exception,
has_data_collection_enabled,
logger,
transaction_from_function,
walk_exception_chain,
Expand Down Expand Up @@ -457,6 +458,39 @@ def _attempt_resolve_again(
_set_transaction_name_and_source(scope, transaction_style, request)


def _get_user_from_request_and_set_on_scope(request: "WSGIRequest") -> None:
user = getattr(request, "user", None)

# Evaluating a SimpleLazyObject in an async view can raise django.core.exceptions.SynchronousOnlyOperation.
# Exit early if the user has not been materialized yet.
is_lazy = isinstance(user, SimpleLazyObject)
if is_lazy and hasattr(request, "_cached_user"):
user = request._cached_user
elif is_lazy:
return

if user is None or not is_authenticated(user):
return

user_info = {}
try:
user_info["id"] = str(user.pk)
except Exception:
pass

try:
user_info["email"] = user.email
except Exception:
pass

try:
user_info["username"] = user.get_username()
except Exception:
pass

sentry_sdk.set_user(user_info)


def _after_get_response(request: "WSGIRequest") -> None:
client = sentry_sdk.get_client()
integration = client.get_integration(DjangoIntegration)
Expand All @@ -468,37 +502,12 @@ def _after_get_response(request: "WSGIRequest") -> None:
_attempt_resolve_again(request, scope, integration.transaction_style)

span_streaming = has_span_streaming_enabled(client.options)
if span_streaming and should_send_default_pii():
user = getattr(request, "user", None)

# Evaluating a SimpleLazyObject in an async view can raise django.core.exceptions.SynchronousOnlyOperation.
# Exit early if the user has not been materialized yet.
is_lazy = isinstance(user, SimpleLazyObject)
if is_lazy and hasattr(request, "_cached_user"):
user = request._cached_user
elif is_lazy:
return

if user is None or not is_authenticated(user):
return

user_info = {}
try:
user_info["id"] = str(user.pk)
except Exception:
pass

try:
user_info["email"] = user.email
except Exception:
pass

try:
user_info["username"] = user.get_username()
except Exception:
pass

sentry_sdk.set_user(user_info)
if span_streaming:
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["user_info"]:
_get_user_from_request_and_set_on_scope(request)
elif should_send_default_pii():
_get_user_from_request_and_set_on_scope(request)


def _patch_get_response() -> None:
Expand Down Expand Up @@ -544,7 +553,12 @@ def wsgi_request_event_processor(event: "Event", hint: "dict[str, Any]") -> "Eve
with capture_internal_exceptions():
DjangoRequestExtractor(request).extract_into_event(event)

if should_send_default_pii():
client_options = sentry_sdk.get_client().options
if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
with capture_internal_exceptions():
_set_user_info(request, event)
elif should_send_default_pii():
with capture_internal_exceptions():
_set_user_info(request, event)

Expand Down
8 changes: 7 additions & 1 deletion sentry_sdk/integrations/django/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from sentry_sdk.utils import (
capture_internal_exceptions,
ensure_integration_enabled,
has_data_collection_enabled,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -70,7 +71,12 @@ def asgi_request_event_processor(event: "Event", hint: "dict[str, Any]") -> "Eve
with capture_internal_exceptions():
DjangoRequestExtractor(request).extract_into_event(event)

if should_send_default_pii():
client_options = sentry_sdk.get_client().options
if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
with capture_internal_exceptions():
_set_user_info(request, event)
elif should_send_default_pii():
with capture_internal_exceptions():
_set_user_info(request, event)

Expand Down
8 changes: 7 additions & 1 deletion sentry_sdk/integrations/litestar.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,14 @@ def retrieve_user_from_scope(scope: "LitestarScope") -> "Optional[dict[str, Any]
@ensure_integration_enabled(LitestarIntegration)
def exception_handler(exc: Exception, scope: "LitestarScope") -> None:
user_info: "Optional[dict[str, Any]]" = None
if should_send_default_pii():
client_options = sentry_sdk.get_client().options

if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
user_info = retrieve_user_from_scope(scope)
elif should_send_default_pii():
user_info = retrieve_user_from_scope(scope)

if user_info and isinstance(user_info, dict):
sentry_scope = sentry_sdk.get_isolation_scope()
sentry_scope.set_user(user_info)
Expand Down
23 changes: 18 additions & 5 deletions sentry_sdk/integrations/pyramid.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
capture_internal_exceptions,
ensure_integration_enabled,
event_from_exception,
has_data_collection_enabled,
reraise,
)

Expand Down Expand Up @@ -86,10 +87,16 @@ def sentry_patched_call_view(

scope = sentry_sdk.get_isolation_scope()

if should_send_default_pii() and has_span_streaming_enabled(client.options):
user_id = authenticated_userid(request)
if user_id:
scope.set_user({"id": user_id})
if has_span_streaming_enabled(client.options):
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["user_info"]:
user_id = authenticated_userid(request)
if user_id:
scope.set_user({"id": user_id})
elif should_send_default_pii():
user_id = authenticated_userid(request)
if user_id:
scope.set_user({"id": user_id})

scope.add_event_processor(
_make_event_processor(weakref.ref(request), integration)
Expand Down Expand Up @@ -229,7 +236,13 @@ def pyramid_event_processor(event: "Event", hint: "Dict[str, Any]") -> "Event":
with capture_internal_exceptions():
PyramidRequestExtractor(request).extract_into_event(event)

if should_send_default_pii():
client_options = sentry_sdk.get_client().options
if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
with capture_internal_exceptions():
user_info = event.setdefault("user", {})
user_info.setdefault("id", authenticated_userid(request))
elif should_send_default_pii():
with capture_internal_exceptions():
user_info = event.setdefault("user", {})
user_info.setdefault("id", authenticated_userid(request))
Expand Down
18 changes: 13 additions & 5 deletions sentry_sdk/integrations/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,12 @@ async def _context_enter(request: "Request") -> None:
sentry_sdk.traces.continue_trace(dict(request.headers))
scope.set_custom_sampling_context({"sanic_request": request})

if should_send_default_pii() and request.remote_addr:
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr)
if request.remote_addr:
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["user_info"]:
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr)
elif should_send_default_pii():
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr)

span = sentry_sdk.traces.start_span(
# Unless the request results in a 404 error, the name and source
Expand Down Expand Up @@ -401,19 +405,23 @@ def _get_request_attributes(request: "Request") -> "Dict[str, Any]":
query=filtered_query or ""
).geturl()

if request.remote_addr:
if client_options["data_collection"]["user_info"]:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_addr

elif should_send_default_pii():
attributes[SPANDATA.URL_FULL] = request.url
attributes["url.path"] = urlparts.path

if urlparts.query:
attributes[SPANDATA.HTTP_QUERY] = urlparts.query

if request.remote_addr:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_addr

if urlparts.scheme:
attributes[SPANDATA.NETWORK_PROTOCOL_NAME] = urlparts.scheme

if should_send_default_pii() and request.remote_addr:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_addr

return attributes


Expand Down
8 changes: 7 additions & 1 deletion sentry_sdk/integrations/starlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,14 @@ def retrieve_user_from_scope(scope: "StarliteScope") -> "Optional[dict[str, Any]
@ensure_integration_enabled(StarliteIntegration)
def exception_handler(exc: Exception, scope: "StarliteScope", _: "State") -> None:
user_info: "Optional[dict[str, Any]]" = None
if should_send_default_pii():
client_options = sentry_sdk.get_client().options

if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
user_info = retrieve_user_from_scope(scope)
elif should_send_default_pii():
user_info = retrieve_user_from_scope(scope)

if user_info and isinstance(user_info, dict):
sentry_scope = sentry_sdk.get_isolation_scope()
sentry_scope.set_user(user_info)
Expand Down
35 changes: 28 additions & 7 deletions sentry_sdk/integrations/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,16 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
sentry_sdk.traces.continue_trace(dict(headers))
scope.set_custom_sampling_context({"tornado_request": self.request})

if should_send_default_pii() and self.request.remote_ip:
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, self.request.remote_ip)
if self.request.remote_ip:
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["user_info"]:
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, self.request.remote_ip
)
elif should_send_default_pii():
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, self.request.remote_ip
)

span_ctx = sentry_sdk.traces.start_span(
name=_DEFAULT_ROOT_SPAN_NAME,
Expand Down Expand Up @@ -218,19 +226,23 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
f"{parsed_url.url}?{filtered_query}" if filtered_query else parsed_url.url
)

if request.remote_ip:
if client_options["data_collection"]["user_info"]:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

elif should_send_default_pii():
attributes[SPANDATA.URL_FULL] = request.full_url()
attributes["url.path"] = request.path

if request.query:
attributes[SPANDATA.URL_QUERY] = request.query

if request.remote_ip:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

if request.protocol:
attributes[SPANDATA.NETWORK_PROTOCOL_NAME] = request.protocol

if should_send_default_pii() and request.remote_ip:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

with capture_internal_exceptions():
raw_data = _get_tornado_request_data(request)
body_data = raw_data.value if isinstance(raw_data, AnnotatedValue) else raw_data
Expand Down Expand Up @@ -282,6 +294,7 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
event["transaction"] = transaction_from_function(method) or ""
event["transaction_info"] = {"source": TransactionSource.COMPONENT}

client_options = sentry_sdk.get_client().options
with capture_internal_exceptions():
extractor = TornadoRequestExtractor(request)
extractor.extract_into_event(event)
Expand All @@ -294,7 +307,6 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
request.path,
)

client_options = sentry_sdk.get_client().options
if has_data_collection_enabled(client_options):
if request.query:
filtered_query = _apply_data_collection_filtering_to_query_string(
Expand All @@ -310,7 +322,16 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
request_info["env"] = {"REMOTE_ADDR": request.remote_ip}
request_info["headers"] = _filter_headers(dict(request.headers))

if should_send_default_pii():
if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
try:
current_user = handler.current_user
except Exception:
current_user = None

if current_user:
event.setdefault("user", {}).setdefault("is_authenticated", True)
elif should_send_default_pii():
try:
current_user = handler.current_user
except Exception:
Expand Down
Loading
Loading