Browse Source

fix(issues) Fix searching by eventid not redirecting (#11827)

The project issue list would automatically redirect to the matching
event when searching by eventid. This adds that behavior to the
organization issue list. The frontend uses the `x-sentry-direct-hit`
header and `matchingEventId` attribute to generate the destination URL.

This path is only followed if the search finds a single group as events
are only unique per project, not per-org.

Fixes APP-1061
Mark Story 6 years ago
parent
commit
7b6e1d81ce

+ 11 - 4
src/sentry/api/endpoints/organization_group_index.py

@@ -107,11 +107,18 @@ class OrganizationGroupIndexEndpoint(OrganizationEventsEndpointBase):
             # check to see if we've got an event ID
             if len(query) == 32:
                 groups = list(
-                    Group.objects.filter_by_event_id(
-                        project_ids,
-                        query,
-                    )
+                    Group.objects.filter_by_event_id(project_ids, query)
                 )
+                if len(groups) == 1:
+                    response = Response(
+                        serialize(
+                            groups, request.user, serializer(
+                                matching_event_id=query
+                            )
+                        )
+                    )
+                    response['X-Sentry-Direct-Hit'] = '1'
+                    return response
 
                 if groups:
                     return Response(serialize(groups, request.user, serializer()))

+ 6 - 1
src/sentry/api/serializers/models/group.py

@@ -602,13 +602,15 @@ class GroupSerializerSnuba(GroupSerializerBase):
 
 
 class StreamGroupSerializerSnuba(GroupSerializerSnuba, GroupStatsMixin):
-    def __init__(self, environment_ids=None, stats_period=None):
+    def __init__(self, environment_ids=None, stats_period=None,
+                 matching_event_id=None):
         super(StreamGroupSerializerSnuba, self).__init__(environment_ids)
 
         if stats_period is not None:
             assert stats_period in self.STATS_PERIOD_CHOICES
 
         self.stats_period = stats_period
+        self.matching_event_id = matching_event_id
 
     def query_tsdb(self, group_ids, query_params):
         return snuba_tsdb.get_range(
@@ -638,4 +640,7 @@ class StreamGroupSerializerSnuba(GroupSerializerSnuba, GroupStatsMixin):
                 self.stats_period: attrs['stats'],
             }
 
+        if self.matching_event_id:
+            result['matchingEventId'] = self.matching_event_id
+
         return result

+ 6 - 1
tests/snuba/api/endpoints/test_organization_group_index.py

@@ -219,16 +219,19 @@ class GroupListTest(APITestCase, SnubaTestCase):
 
         response = self.client.get(u'{}?query={}'.format(self.path, 'c' * 32), format='json')
         assert response.status_code == 200
+        assert response['X-Sentry-Direct-Hit'] == '1'
         assert len(response.data) == 1
         assert response.data[0]['id'] == six.text_type(group.id)
+        assert response.data[0]['matchingEventId'] == event_id
 
     def test_lookup_by_event_id_with_whitespace(self):
         project = self.project
         project.update_option('sentry:resolve_age', 1)
         group = self.create_group(checksum='a' * 32)
+        event_id = 'c' * 32
         self.create_group(checksum='b' * 32)
         EventMapping.objects.create(
-            event_id='c' * 32,
+            event_id=event_id,
             project=group.project,
             group=group,
         )
@@ -238,8 +241,10 @@ class GroupListTest(APITestCase, SnubaTestCase):
             u'{}?query=%20%20{}%20%20'.format(self.path, 'c' * 32), format='json'
         )
         assert response.status_code == 200
+        assert response['X-Sentry-Direct-Hit'] == '1'
         assert len(response.data) == 1
         assert response.data[0]['id'] == six.text_type(group.id)
+        assert response.data[0]['matchingEventId'] == event_id
 
     def test_lookup_by_unknown_event_id(self):
         project = self.project