Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/sentry/apidocs/examples/event_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,8 @@ class EventExamples:
{
"id": "53aa54ab27474eaab1fc1d0f7f86d2f1",
"latestEvent": EVENT_RESPONSE,
"mergedBySeer": False,
"mergedBySeer": True,
"seerMatchDistance": 0.01,
}
],
response_only=True,
Expand Down
11 changes: 8 additions & 3 deletions src/sentry/issues/endpoints/group_hashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class GroupHashesResult(TypedDict):
id: str
latestEvent: EventSerializerResponse | SimpleEventSerializerResponse | None
mergedBySeer: bool
seerMatchDistance: float | None


@extend_schema(tags=["Events"])
Expand Down Expand Up @@ -180,15 +181,19 @@ def __handle_result(
grouphash: GroupHash | None = None,
) -> GroupHashesResult:
event = eventstore.backend.get_event_by_id(project_id, result["event_id"])
merged_by_seer = bool(
grouphash and grouphash.metadata and grouphash.metadata.seer_matched_grouphash
)
if grouphash and grouphash.metadata and grouphash.metadata.seer_matched_grouphash:
merged_by_seer = True
seer_match_distance = grouphash.metadata.seer_match_distance
else:
merged_by_seer = False
seer_match_distance = None

serializer = EventSerializer if full else SimpleEventSerializer
response: GroupHashesResult = {
"id": result["primary_hash"],
"latestEvent": serialize(event, user, serializer()),
"mergedBySeer": merged_by_seer,
"seerMatchDistance": seer_match_distance,
}

return response
29 changes: 9 additions & 20 deletions tests/sentry/issues/endpoints/test_group_hashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from sentry.eventstream.snuba import SnubaEventStream
from sentry.models.grouphash import GroupHash
from sentry.models.grouphashmetadata import GroupHashMetadata
from sentry.testutils.cases import APITestCase, SnubaTestCase
from sentry.testutils.helpers.datetime import before_now

Expand Down Expand Up @@ -120,32 +119,20 @@ def test_return_multiple_hashes_with_seer_match(self) -> None:

eventstream.end_merge(state)

# Get the grouphashes for both events (refresh after merge)
# Get the grouphashes for both events
hash1 = event1.get_primary_hash()
hash2 = event2.get_primary_hash()

# Refresh the grouphashes after merge to get updated group assignments
grouphash1 = GroupHash.objects.get(project=self.project, hash=hash1)
grouphash2 = GroupHash.objects.get(project=self.project, hash=hash2)
assert grouphash2.metadata

# Manually update grouphash2 to point to the merged group (event1.group_id)
# Manually update grouphash2 to point to the merged group (event1.group_id) and its metadata
# to reflect the Seer match
grouphash2.group = event1.group
grouphash2.metadata.seer_matched_grouphash = grouphash1
grouphash2.metadata.seer_match_distance = 0.01
grouphash2.save()

# Get or create metadata for both grouphashes
metadata1, _ = GroupHashMetadata.objects.get_or_create(
grouphash=grouphash1, defaults={"schema_version": "8"}
)
metadata2, _ = GroupHashMetadata.objects.get_or_create(
grouphash=grouphash2,
defaults={
"schema_version": "8",
"seer_matched_grouphash": grouphash1, # hash2 points to hash1 as its seer match
},
)
# Update the seer match if metadata already existed
metadata2.seer_matched_grouphash = grouphash1
metadata2.save()
grouphash2.metadata.save()

url = f"/api/0/organizations/{self.organization.slug}/issues/{event1.group_id}/hashes/"
response = self.client.get(url, format="json")
Expand All @@ -159,9 +146,11 @@ def test_return_multiple_hashes_with_seer_match(self) -> None:

# hash1 should not be matched by seer (it's the parent)
assert hash1_data["mergedBySeer"] is False
assert hash1_data["seerMatchDistance"] is None

# hash2 should be matched by seer (it points to hash1)
assert hash2_data["mergedBySeer"] is True
assert hash2_data["seerMatchDistance"] == 0.01

def test_full_param(self) -> None:
self.login_as(user=self.user)
Expand Down
Loading