From 5e7956b628744f1943842c24e61b8a78e251df2e Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 29 Sep 2026 12:56:45 -0400 Subject: [PATCH 1/3] ref(asgi): Drop `send_default_pii` support in `_get_request_data` Always filter the query string through the `data_collection` `url_query_params` setting. The legacy `send_default_pii` path is resolved into an equivalent `data_collection` default, so the raw query string is no longer passed through. Update the Django ASGI and FastAPI tests to configure `data_collection` instead of `send_default_pii`. Refs PY-2798 Refs #7566 --- sentry_sdk/integrations/_asgi_common.py | 21 ++++++++------------- tests/integrations/django/asgi/test_asgi.py | 2 +- tests/integrations/fastapi/test_fastapi.py | 8 ++++---- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/sentry_sdk/integrations/_asgi_common.py b/sentry_sdk/integrations/_asgi_common.py index 640412657d..3b50addd10 100644 --- a/sentry_sdk/integrations/_asgi_common.py +++ b/sentry_sdk/integrations/_asgi_common.py @@ -123,19 +123,14 @@ def _get_request_data( request_data["headers"] = _filter_headers(headers) - if has_data_collection_enabled(client_options): - qs = _get_query(asgi_scope) - if qs: - filtered_query_string = ( - _apply_data_collection_filtering_to_query_string( - query_string=qs, - behaviour=client_options["data_collection"]["url_query_params"], - ) - ) - if filtered_query_string: - request_data["query_string"] = filtered_query_string - else: - request_data["query_string"] = _get_query(asgi_scope) + qs = _get_query(asgi_scope) + if qs: + filtered_query_string = _apply_data_collection_filtering_to_query_string( + query_string=qs, + behaviour=client_options["data_collection"]["url_query_params"], + ) + if filtered_query_string: + request_data["query_string"] = filtered_query_string request_data["url"] = _get_url( asgi_scope, diff --git a/tests/integrations/django/asgi/test_asgi.py b/tests/integrations/django/asgi/test_asgi.py index 3a402ec7b4..d03b4dae90 100644 --- a/tests/integrations/django/asgi/test_asgi.py +++ b/tests/integrations/django/asgi/test_asgi.py @@ -52,7 +52,7 @@ async def test_basic( ): sentry_init( integrations=[DjangoIntegration()], - send_default_pii=True, + data_collection={}, ) import channels # type: ignore[import-not-found] diff --git a/tests/integrations/fastapi/test_fastapi.py b/tests/integrations/fastapi/test_fastapi.py index 0439326881..c0b7bd449b 100644 --- a/tests/integrations/fastapi/test_fastapi.py +++ b/tests/integrations/fastapi/test_fastapi.py @@ -128,7 +128,7 @@ async def body_form( async def test_request_info_json_body(sentry_init, capture_items): sentry_init( traces_sample_rate=1.0, - send_default_pii=True, + data_collection={}, integrations=[StarletteIntegration()], ) @@ -214,7 +214,7 @@ async def test_formdata_request_body(sentry_init, capture_items): async def test_request_body_too_big(sentry_init, capture_items): sentry_init( traces_sample_rate=1.0, - send_default_pii=True, + data_collection={}, integrations=[StarletteIntegration()], ) @@ -343,7 +343,7 @@ async def test_response(sentry_init, capture_events): sentry_init( integrations=[StarletteIntegration(), FastApiIntegration()], traces_sample_rate=1.0, - send_default_pii=True, + data_collection={}, ) app = fastapi_app_factory() @@ -818,7 +818,7 @@ def test_transaction_http_method_custom(sentry_init, capture_items): def test_request_url(sentry_init, capture_items): sentry_init( traces_sample_rate=1.0, - send_default_pii=True, + data_collection={}, integrations=[ StarletteIntegration(), ], From dbbc12b2bf665f58106885cc28ea4bc319cff4e0 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 29 Sep 2026 13:10:26 -0400 Subject: [PATCH 2/3] ref(asgi): Drop `send_default_pii` support for user info in `_get_request_data` Read `REMOTE_ADDR` from `data_collection["user_info"]` only. The client already resolves `send_default_pii` into `data_collection` at init, so the legacy `should_send_default_pii()` fallback is redundant. Update the ASGI and Django ASGI tests to configure `data_collection` instead of `send_default_pii`, and remove the legacy `send_default_pii` parametrized cases. --- sentry_sdk/integrations/_asgi_common.py | 5 +- tests/integrations/asgi/test_asgi.py | 79 ++------------------- tests/integrations/django/asgi/test_asgi.py | 4 +- 3 files changed, 9 insertions(+), 79 deletions(-) diff --git a/sentry_sdk/integrations/_asgi_common.py b/sentry_sdk/integrations/_asgi_common.py index 3b50addd10..fd9ee2b0ec 100644 --- a/sentry_sdk/integrations/_asgi_common.py +++ b/sentry_sdk/integrations/_asgi_common.py @@ -141,10 +141,7 @@ def _get_request_data( client = asgi_scope.get("client") if client: - if has_data_collection_enabled(client_options): - if client_options["data_collection"]["user_info"]: - request_data["env"] = {"REMOTE_ADDR": _get_ip(asgi_scope)} - elif should_send_default_pii(): + if client_options["data_collection"]["user_info"]: request_data["env"] = {"REMOTE_ADDR": _get_ip(asgi_scope)} return request_data diff --git a/tests/integrations/asgi/test_asgi.py b/tests/integrations/asgi/test_asgi.py index b8e1e20d5c..1219eaa679 100644 --- a/tests/integrations/asgi/test_asgi.py +++ b/tests/integrations/asgi/test_asgi.py @@ -167,18 +167,13 @@ def test_invalid_transaction_style(asgi3_app): @pytest.mark.asyncio -@pytest.mark.parametrize( - "should_send_pii", - [True, False], -) async def test_capture_transaction( sentry_init, asgi3_app, capture_items, - should_send_pii, ): sentry_init( - send_default_pii=should_send_pii, + data_collection={}, traces_sample_rate=1.0, ) app = SentryAsgiMiddleware(asgi3_app) @@ -202,13 +197,7 @@ async def test_capture_transaction( assert span["attributes"]["http.request.method"] == "GET" assert span["attributes"]["http.request.header.host"] == "localhost" assert span["attributes"]["http.request.header.user-agent"] == "ASGI-Test-Client" - - if should_send_pii: - assert ( - span["attributes"]["url.full"] == "http://localhost/some_url?somevalue=123" - ) - assert span["attributes"]["url.path"] == "/some_url" - assert span["attributes"]["http.query"] == "somevalue=123" + assert span["attributes"]["url.full"] == "http://localhost/some_url?somevalue=123" @pytest.mark.asyncio @@ -218,7 +207,7 @@ async def test_capture_transaction_with_error( capture_items, ): sentry_init( - send_default_pii=True, + data_collection={}, traces_sample_rate=1.0, ) @@ -397,7 +386,7 @@ async def test_websocket( request, ): sentry_init( - send_default_pii=True, + data_collection={}, traces_sample_rate=1.0, ) @@ -438,7 +427,7 @@ async def test_auto_session_tracking_with_aggregates( sentry_init, asgi3_app, capture_envelopes ): sentry_init( - send_default_pii=True, + data_collection={}, traces_sample_rate=1.0, ) app = SentryAsgiMiddleware(asgi3_app) @@ -505,7 +494,7 @@ async def test_transaction_style( expected_source, ): sentry_init( - send_default_pii=True, + data_collection={}, traces_sample_rate=1.0, ) app = SentryAsgiMiddleware(asgi3_app, transaction_style=transaction_style) @@ -783,7 +772,6 @@ async def test_get_request_attributes_url_with_filtered_host( # the host header value, but "url.full" must still resolve rather than embedding # the substituted value. sentry_init( - send_default_pii=True, traces_sample_rate=1.0, data_collection={ "http_headers": {"request": {"mode": "allowlist", "terms": []}} @@ -842,20 +830,6 @@ def _http_scope(): @pytest.mark.parametrize( "init_kwargs, request_url, expected_query, expected_url_full", [ - pytest.param( - {"send_default_pii": True}, - "/foo?" + QUERY_STRING, - QUERY_STRING, - "http://example.com/foo?" + QUERY_STRING, - id="send_default_pii_true", - ), - pytest.param( - {"send_default_pii": False}, - "/foo?" + QUERY_STRING, - None, - None, - id="send_default_pii_false", - ), pytest.param( {}, "/foo?" + QUERY_STRING, @@ -888,16 +862,6 @@ def _http_scope(): "http://example.com/foo", id="data_collection_off", ), - pytest.param( - { - "send_default_pii": True, - "data_collection": {"url_query_params": {"mode": "off"}}, - }, - "/foo?" + QUERY_STRING, - None, - "http://example.com/foo", - id="data_collection_wins_over_send_default_pii", - ), pytest.param( {"_experiments": {"data_collection": {}}}, "/foo", @@ -957,27 +921,6 @@ async def test_get_request_attributes_query_data_collection( True, id="dc_default_user_info", ), - pytest.param( - { - "send_default_pii": True, - "data_collection": {"user_info": False}, - }, - True, - False, - id="dc_wins_over_pii", - ), - pytest.param( - {"send_default_pii": True}, - True, - True, - id="legacy_pii_true", - ), - pytest.param( - {"send_default_pii": False}, - True, - False, - id="legacy_pii_false", - ), pytest.param( {"data_collection": {}}, False, @@ -1149,8 +1092,6 @@ async def test_custom_transaction_name( @pytest.mark.parametrize( "init_kwargs, expect_ip", [ - pytest.param({"send_default_pii": True}, True, id="legacy_pii_true"), - pytest.param({"send_default_pii": False}, False, id="legacy_pii_false"), pytest.param( {"data_collection": {}}, True, @@ -1166,14 +1107,6 @@ async def test_custom_transaction_name( False, id="dc_user_info_false", ), - pytest.param( - { - "send_default_pii": True, - "data_collection": {"user_info": False}, - }, - False, - id="dc_wins_over_pii", - ), ], ) async def test_user_ip_address_on_all_spans( diff --git a/tests/integrations/django/asgi/test_asgi.py b/tests/integrations/django/asgi/test_asgi.py index d03b4dae90..50608d1a25 100644 --- a/tests/integrations/django/asgi/test_asgi.py +++ b/tests/integrations/django/asgi/test_asgi.py @@ -171,7 +171,7 @@ async def test_async_views_concurrent_execution( settings.MIDDLEWARE = [] sentry_init( integrations=[DjangoIntegration()], - send_default_pii=True, + data_collection={}, ) application = make_asgi_application() @@ -211,7 +211,7 @@ async def test_async_middleware_that_is_function_concurrent_execution( ] sentry_init( integrations=[DjangoIntegration()], - send_default_pii=True, + data_collection={}, ) application = make_asgi_application() From 72e82144587d8fe78a2e1601e084b86f7b14d002 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 1 Oct 2026 09:01:22 -0400 Subject: [PATCH 3/3] . --- tests/integrations/asgi/test_asgi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integrations/asgi/test_asgi.py b/tests/integrations/asgi/test_asgi.py index 07c5b3bb5e..0d565a6bb4 100644 --- a/tests/integrations/asgi/test_asgi.py +++ b/tests/integrations/asgi/test_asgi.py @@ -212,8 +212,8 @@ async def test_capture_transaction( assert span["attributes"]["network.protocol.name"] == "http" assert span["attributes"]["http.request.method"] == "GET" - assert span["attributes"]["http.request.header.host"] == "localhost" - assert span["attributes"]["http.request.header.user-agent"] == "ASGI-Test-Client" + assert span["attributes"]["http.request.header.host"] == ["localhost"] + assert span["attributes"]["http.request.header.user-agent"] == ["ASGI-Test-Client"] assert span["attributes"]["url.full"] == "http://localhost/some_url?somevalue=123"