Skip to content

Commit d21efa9

Browse files
authored
feat(aiohttp): Gate user info behind data_collection config (#6874)
Apply the data_collection.user_info setting to the aiohttp integration's user IP collection under span streaming, giving it precedence over the legacy send_default_pii boolean when explicitly configured. This covers both the client.address span attribute and the user.ip_address scope attribute, mirroring the behavior already shipped for Flask, WSGI, ASGI, Django, Sanic, Tornado, and Pyramid. Add test_user_address_with_data_collection_and_span_streaming, parametrized with the shared DATA_COLLECTION_USER_INFO_CASES matrix from tests/integrations/utils.py, and remove the now-redundant IP assertion block from test_sensitive_header_passthrough_with_pii_span_streaming that its TODO reserved for this change. Refs PY-2583 Fixes #6746
1 parent 1bed4e2 commit d21efa9

2 files changed

Lines changed: 56 additions & 16 deletions

File tree

sentry_sdk/integrations/aiohttp.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ async def sentry_app_handle(
165165
)
166166

167167
url_attributes = {}
168+
client_address_attributes = {}
169+
168170
if has_data_collection_enabled(client.options):
169171
url_attributes["url.full"] = "%s://%s%s" % (
170172
request.scheme,
@@ -188,6 +190,15 @@ async def sentry_app_handle(
188190
"?" + filtered_query_string
189191
)
190192

193+
if request.remote:
194+
if client.options["data_collection"]["user_info"]:
195+
client_address_attributes["client.address"] = (
196+
request.remote
197+
)
198+
scope.set_attribute(
199+
SPANDATA.USER_IP_ADDRESS, request.remote
200+
)
201+
191202
elif should_send_default_pii():
192203
url_full = "%s://%s%s" % (
193204
request.scheme,
@@ -201,12 +212,13 @@ async def sentry_app_handle(
201212
url_attributes["url.full"] = url_full
202213
url_attributes["url.path"] = request.path
203214

204-
client_address_attributes = {}
205-
if should_send_default_pii() and request.remote:
206-
client_address_attributes["client.address"] = request.remote
207-
scope.set_attribute(
208-
SPANDATA.USER_IP_ADDRESS, request.remote
209-
)
215+
if request.remote:
216+
client_address_attributes["client.address"] = (
217+
request.remote
218+
)
219+
scope.set_attribute(
220+
SPANDATA.USER_IP_ADDRESS, request.remote
221+
)
210222

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

tests/integrations/aiohttp/test_aiohttp.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727
from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE
2828
from tests.conftest import ApproxDict
29+
from tests.integrations.utils import DATA_COLLECTION_USER_INFO_CASES
2930

3031

3132
@pytest.mark.asyncio
@@ -1208,6 +1209,43 @@ async def hello(request):
12081209
assert "http.request.header.host" in server_span["attributes"]
12091210

12101211

1212+
@pytest.mark.asyncio
1213+
@pytest.mark.parametrize("init_kwargs, expect_ip", DATA_COLLECTION_USER_INFO_CASES)
1214+
async def test_user_address_with_data_collection_and_span_streaming(
1215+
sentry_init, aiohttp_client, capture_items, init_kwargs, expect_ip
1216+
):
1217+
sentry_init(
1218+
integrations=[AioHttpIntegration()],
1219+
traces_sample_rate=1.0,
1220+
trace_lifecycle="stream",
1221+
**init_kwargs,
1222+
)
1223+
1224+
async def hello(request):
1225+
return web.Response(text="hello")
1226+
1227+
app = web.Application()
1228+
app.router.add_get("/", hello)
1229+
1230+
items = capture_items("span")
1231+
1232+
client = await aiohttp_client(app)
1233+
resp = await client.get("/")
1234+
assert resp.status == 200
1235+
1236+
sentry_sdk.flush()
1237+
1238+
(server_span,) = [item.payload for item in items]
1239+
assert server_span["attributes"]["sentry.origin"] == "auto.http.aiohttp"
1240+
1241+
if expect_ip:
1242+
assert server_span["attributes"]["client.address"] == "127.0.0.1"
1243+
assert server_span["attributes"]["user.ip_address"] == "127.0.0.1"
1244+
else:
1245+
assert "client.address" not in server_span["attributes"]
1246+
assert "user.ip_address" not in server_span["attributes"]
1247+
1248+
12111249
@pytest.mark.asyncio
12121250
async def test_sensitive_header_scrubbing_span_streaming(
12131251
sentry_init, aiohttp_client, capture_items
@@ -1420,16 +1458,6 @@ async def hello(request):
14201458
== expected["cookie"]
14211459
)
14221460

1423-
# client.address and user.ip_address is captured under send_default_pii=True.
1424-
# TODO: This block will eventually need to be removed from this test into a separate
1425-
# test once data collection gating is introduced on these values
1426-
if options["send_default_pii"]:
1427-
assert server_span["attributes"]["client.address"] == "127.0.0.1"
1428-
assert server_span["attributes"]["user.ip_address"] == "127.0.0.1"
1429-
else:
1430-
assert "user.ip_address" not in server_span["attributes"]
1431-
assert "client.address" not in server_span["attributes"]
1432-
14331461

14341462
@pytest.mark.asyncio
14351463
async def test_sensitive_header_passthrough_with_pii_span_streaming_without_data_collection(

0 commit comments

Comments
 (0)