Skip to content

Commit 885fd78

Browse files
aliu39cmanallen
andauthored
feat(replay): make user.geo fields searchable (#91313)
Depends on - getsentry/snuba#7173 - getsentry/snuba#7174 - getsentry/snuba#7175 Ref - getsentry/team-replay#566 --------- Co-authored-by: Colton Allen <colton.allen@sentry.io>
1 parent eedde2f commit 885fd78

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

src/sentry/replays/post_process.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,20 @@ class BrowserResponseType(TypedDict, total=False):
3232
version: str | None
3333

3434

35+
class UserGeoResponseType(TypedDict, total=False):
36+
city: str | None
37+
country_code: str | None
38+
region: str | None
39+
subdivision: str | None
40+
41+
3542
class UserResponseType(TypedDict, total=False):
3643
id: str | None
3744
username: str | None
3845
email: str | None
3946
ip: str | None
4047
display_name: str | None
48+
geo: UserGeoResponseType
4149

4250

4351
class OTAUpdatesResponseType(TypedDict, total=False):
@@ -132,6 +140,12 @@ def generate_normalized_output(response: list[dict[str, Any]]) -> Generator[Repl
132140
"username": item.pop("user_username", None),
133141
"email": item.pop("user_email", None),
134142
"ip": item.pop("user_ip", None),
143+
"geo": {
144+
"city": item.pop("user_geo_city", None),
145+
"country_code": item.pop("user_geo_country_code", None),
146+
"region": item.pop("user_geo_region", None),
147+
"subdivision": item.pop("user_geo_subdivision", None),
148+
},
135149
}
136150
ret_item["user"]["display_name"] = (
137151
ret_item["user"]["username"]
@@ -225,7 +239,19 @@ def _archived_row(replay_id: str, project_id: int) -> dict[str, Any]:
225239
"error_ids": [],
226240
"environment": None,
227241
"tags": [],
228-
"user": {"id": "Archived Replay", "display_name": "Archived Replay"},
242+
"user": {
243+
"id": "Archived Replay",
244+
"display_name": "Archived Replay",
245+
"username": None,
246+
"email": None,
247+
"ip": None,
248+
"geo": {
249+
"city": None,
250+
"country_code": None,
251+
"region": None,
252+
"subdivision": None,
253+
},
254+
},
229255
"sdk": {"name": None, "version": None},
230256
"os": {"name": None, "version": None},
231257
"browser": {"name": None, "version": None},

src/sentry/replays/query.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,10 @@ def _empty_uuids_lambda():
564564
"user.email": ["user_email"],
565565
"user.username": ["user_username"],
566566
"user.ip": ["user_ip"],
567+
"user.geo.city": ["user_geo_city"],
568+
"user.geo.country_code": ["user_geo_country_code"],
569+
"user.geo.region": ["user_geo_region"],
570+
"user.geo.subdivision": ["user_geo_subdivision"],
567571
"os.name": ["os_name"],
568572
"os.version": ["os_version"],
569573
"browser.name": ["browser_name"],
@@ -719,6 +723,10 @@ def _empty_uuids_lambda():
719723
parameters=[anyIfNonZeroIP(column_name="ip_address_v4", aliased=False)],
720724
alias="user_ip",
721725
),
726+
"user_geo_city": anyIf(column_name="user_geo_city"),
727+
"user_geo_country_code": anyIf(column_name="user_geo_country_code"),
728+
"user_geo_region": anyIf(column_name="user_geo_region"),
729+
"user_geo_subdivision": anyIf(column_name="user_geo_subdivision"),
722730
"os_name": anyIf(column_name="os_name"),
723731
"os_version": anyIf(column_name="os_version"),
724732
"browser_name": anyIf(column_name="browser_name"),

src/sentry/replays/testutils.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ def mock_expected_response(
125125
"email": kwargs.pop("user_email", "username@example.com"),
126126
"username": kwargs.pop("user_name", "username"),
127127
"ip": kwargs.pop("user_ip", "127.0.0.1"),
128+
"geo": {
129+
"city": kwargs.pop("user_geo_city", "San Francisco"),
130+
"country_code": kwargs.pop("user_geo_country_code", "USA"),
131+
"region": kwargs.pop("user_geo_region", "United States"),
132+
"subdivision": kwargs.pop("user_geo_subdivision", "California"),
133+
},
128134
},
129135
"tags": kwargs.pop("tags", {}),
130136
"activity": kwargs.pop("activity", 0),
@@ -185,6 +191,12 @@ def mock_replay(
185191
"username": kwargs.pop("user_name", "username"),
186192
"email": kwargs.pop("user_email", "username@example.com"),
187193
"ip_address": kwargs.pop("ipv4", "127.0.0.1"),
194+
"geo": {
195+
"city": kwargs.pop("user_geo_city", "San Francisco"),
196+
"country_code": kwargs.pop("user_geo_country_code", "USA"),
197+
"region": kwargs.pop("user_geo_region", "United States"),
198+
"subdivision": kwargs.pop("user_geo_subdivision", "California"),
199+
},
188200
},
189201
"sdk": {
190202
"name": kwargs.pop("sdk_name", "sentry.javascript.react"),

src/sentry/replays/usecases/query/configs/aggregate.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ def array_string_field(column_name: str) -> StringColumnField:
134134
"user.id": string_field("user_id"),
135135
"user.ip_address": NullableStringColumnField("ip_address_v4", parse_ipv4, SumOfIPv4Scalar),
136136
"user.username": string_field("user_name"),
137+
"user.geo.city": string_field("user_geo_city"),
138+
"user.geo.country_code": string_field("user_geo_country_code"),
139+
"user.geo.region": string_field("user_geo_region"),
140+
"user.geo.subdivision": string_field("user_geo_subdivision"),
137141
"viewed_by_id": IntegerColumnField("viewed_by_id", parse_int, SumOfIntegerIdScalar),
138142
"warning_ids": UUIDColumnField("warning_id", parse_uuid, SumOfUUIDScalar),
139143
}

tests/sentry/replays/test_organization_replay_index.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,17 @@ def test_get_replays_browse_screen_fields(self):
235235
assert "urls" in response_data["data"][0]
236236
assert "user" in response_data["data"][0]
237237

238-
assert len(response_data["data"][0]["user"]) == 5
238+
assert len(response_data["data"][0]["user"]) == 6
239239
assert "id" in response_data["data"][0]["user"]
240240
assert "username" in response_data["data"][0]["user"]
241241
assert "email" in response_data["data"][0]["user"]
242242
assert "ip" in response_data["data"][0]["user"]
243243
assert "display_name" in response_data["data"][0]["user"]
244+
assert "geo" in response_data["data"][0]["user"]
245+
assert "city" in response_data["data"][0]["user"]["geo"]
246+
assert "country_code" in response_data["data"][0]["user"]["geo"]
247+
assert "region" in response_data["data"][0]["user"]["geo"]
248+
assert "subdivision" in response_data["data"][0]["user"]["geo"]
244249

245250
def test_get_replays_tags_field(self):
246251
"""Test replay response with fields requested in production."""
@@ -658,6 +663,11 @@ def test_get_replays_user_filters(self):
658663
"user.ip:127.0.0.1",
659664
"user.ip:[127.0.0.1, 10.0.4.4]",
660665
"!user.ip:[127.1.1.1, 10.0.4.4]",
666+
'user.geo.city:"San Francisco"',
667+
"user.geo.country_code:USA",
668+
'user.geo.region:"United States"',
669+
"user.geo.subdivision:California",
670+
'user.geo.city:"San Francisco" AND user.geo.country_code:USA AND user.geo.region:"United States" AND user.geo.subdivision:California',
661671
"sdk.name:sentry.javascript.react",
662672
"ota_updates.channel:stable",
663673
"ota_updates.runtime_version:1.2.3",
@@ -774,6 +784,12 @@ def test_get_replays_user_filters(self):
774784
"seen_by_me:false",
775785
"user.email:[user2@example.com]",
776786
"!user.email:[username@example.com, user2@example.com]",
787+
'!user.geo.city:"San Francisco"',
788+
"!user.geo.country_code:USA",
789+
'!user.geo.region:"United States"',
790+
"!user.geo.subdivision:California",
791+
'user.geo.city:"San Francisco" AND !user.geo.country_code:USA',
792+
'!user.geo.subdivision:California OR !user.geo.region:"United States"',
777793
"!ota_updates.channel:stable",
778794
"!ota_updates.runtime_version:1.2.3",
779795
"!ota_updates.update_id:1234567890",
@@ -1068,7 +1084,19 @@ def test_archived_records_are_null_fields(self):
10681084
"error_ids": [],
10691085
"environment": None,
10701086
"tags": [],
1071-
"user": {"id": "Archived Replay", "display_name": "Archived Replay"},
1087+
"user": {
1088+
"id": "Archived Replay",
1089+
"display_name": "Archived Replay",
1090+
"username": None,
1091+
"email": None,
1092+
"ip": None,
1093+
"geo": {
1094+
"city": None,
1095+
"country_code": None,
1096+
"region": None,
1097+
"subdivision": None,
1098+
},
1099+
},
10721100
"sdk": {"name": None, "version": None},
10731101
"os": {"name": None, "version": None},
10741102
"browser": {"name": None, "version": None},

0 commit comments

Comments
 (0)