Browse Source

fix(api): Add date filtering support to org group index (#11477)

Jess MacQueen 6 years ago
parent
commit
a75701522c

+ 12 - 1
src/sentry/api/endpoints/organization_group_index.py

@@ -11,6 +11,7 @@ from sentry.api.bases import OrganizationEventsEndpointBase
 from sentry.api.helpers.group_search import build_query_params_from_request, get_by_short_id, ValidationError
 from sentry.api.serializers import serialize
 from sentry.api.serializers.models.group import StreamGroupSerializerSnuba
+from sentry.api.utils import get_date_range_from_params, InvalidParams
 from sentry.models import Environment, Group, GroupStatus, Project
 from sentry.search.snuba.backend import SnubaSearchBackend
 
@@ -109,6 +110,7 @@ class OrganizationGroupIndexEndpoint(OrganizationEventsEndpointBase):
         if not project_ids:
             return Response([])
 
+        # we ignore date range for both short id and event ids
         query = request.GET.get('query', '').strip()
         if query:
             # check to see if we've got an event ID
@@ -135,9 +137,18 @@ class OrganizationGroupIndexEndpoint(OrganizationEventsEndpointBase):
                     response['X-Sentry-Direct-Hit'] = '1'
                     return response
 
+        try:
+            start, end = get_date_range_from_params(request.GET)
+        except InvalidParams as exc:
+            return Response({'detail': exc.message}, status=400)
+
         try:
             cursor_result, query_kwargs = self._search(
-                request, organization, project_ids, environments, {'count_hits': True})
+                request, organization, project_ids, environments, {
+                    'count_hits': True,
+                    'date_to': end,
+                    'date_from': start,
+                })
         except ValidationError as exc:
             return Response({'detail': six.text_type(exc)}, status=400)
 

+ 84 - 12
tests/snuba/api/endpoints/test_organization_group_index.py

@@ -40,6 +40,10 @@ class GroupListTest(APITestCase, SnubaTestCase):
             checksum='a' * 32,
             last_seen=now - timedelta(seconds=1),
         )
+        self.create_event(
+            group=group1,
+            datetime=now - timedelta(seconds=1),
+        )
         self.login_as(user=self.user)
 
         response = self.client.get(
@@ -69,20 +73,20 @@ class GroupListTest(APITestCase, SnubaTestCase):
         now = timezone.now().replace(microsecond=0)
         group1 = self.create_group(
             project=self.project,
-            last_seen=now - timedelta(seconds=1),
+            last_seen=now - timedelta(seconds=2),
         )
         self.create_event(
             group=group1,
-            datetime=now - timedelta(seconds=1),
+            datetime=now - timedelta(seconds=2),
         )
         group2 = self.create_group(
             project=self.project,
-            last_seen=now,
+            last_seen=now - timedelta(seconds=1),
         )
         self.create_event(
             stacktrace=[['foo.py']],
             group=group2,
-            datetime=now,
+            datetime=now - timedelta(seconds=1),
         )
         self.login_as(user=self.user)
         response = self.client.get(
@@ -151,13 +155,22 @@ class GroupListTest(APITestCase, SnubaTestCase):
         project = self.project
         project.update_option('sentry:resolve_age', 1)
         now = timezone.now()
-        self.create_group(
+        group = self.create_group(
             checksum='a' * 32,
             last_seen=now - timedelta(days=1),
         )
+        self.create_event(
+            group=group,
+            datetime=now - timedelta(days=1),
+        )
         group2 = self.create_group(
             checksum='b' * 32,
-            last_seen=now,
+            last_seen=now - timedelta(seconds=1),
+        )
+        self.create_event(
+            group=group2,
+            datetime=now - timedelta(seconds=1),
+            stacktrace=[['foo.py']],
         )
 
         self.login_as(user=self.user)
@@ -252,6 +265,7 @@ class GroupListTest(APITestCase, SnubaTestCase):
         assert len(response.data) == 0
 
     def test_lookup_by_first_release(self):
+        now = timezone.now()
         self.login_as(self.user)
         project = self.project
         project2 = self.create_project(name='baz', organization=project.organization)
@@ -259,7 +273,15 @@ class GroupListTest(APITestCase, SnubaTestCase):
         release.add_project(project)
         release.add_project(project2)
         group = self.create_group(checksum='a' * 32, project=project, first_release=release)
+        self.create_event(
+            group=group,
+            datetime=now - timedelta(seconds=1),
+        )
         group2 = self.create_group(checksum='b' * 32, project=project2, first_release=release)
+        self.create_event(
+            group=group2,
+            datetime=now - timedelta(seconds=1),
+        )
         url = '%s?query=%s' % (self.path, quote('first-release:"%s"' % release.version))
         response = self.client.get(url, format='json')
         issues = json.loads(response.content)
@@ -274,7 +296,7 @@ class GroupListTest(APITestCase, SnubaTestCase):
         release = Release.objects.create(organization=project.organization, version='12345')
         release.add_project(project)
         self.create_event(
-            group_id=self.group.id,
+            group=self.group,
             datetime=self.min_ago,
             tags={'sentry:release': release.version},
         )
@@ -287,27 +309,47 @@ class GroupListTest(APITestCase, SnubaTestCase):
         assert int(issues[0]['id']) == self.group.id
 
     def test_pending_delete_pending_merge_excluded(self):
-        self.create_group(
+        group = self.create_group(
             checksum='a' * 32,
             status=GroupStatus.PENDING_DELETION,
         )
-        group = self.create_group(
+        self.create_event(
+            group=group,
+            datetime=self.min_ago,
+            data={'checksum': 'a' * 32},
+        )
+        group2 = self.create_group(
             checksum='b' * 32,
         )
-        self.create_group(
+        self.create_event(
+            group=group2,
+            datetime=self.min_ago,
+            data={'checksum': 'b' * 32},
+        )
+        group3 = self.create_group(
             checksum='c' * 32,
             status=GroupStatus.DELETION_IN_PROGRESS,
         )
-        self.create_group(
+        self.create_event(
+            group=group3,
+            datetime=self.min_ago,
+            data={'checksum': 'c' * 32},
+        )
+        group4 = self.create_group(
             checksum='d' * 32,
             status=GroupStatus.PENDING_MERGE,
         )
+        self.create_event(
+            group=group4,
+            datetime=self.min_ago,
+            data={'checksum': 'd' * 32},
+        )
 
         self.login_as(user=self.user)
 
         response = self.client.get(self.path, format='json')
         assert len(response.data) == 1
-        assert response.data[0]['id'] == six.text_type(group.id)
+        assert response.data[0]['id'] == six.text_type(group2.id)
 
     def test_filters_based_on_retention(self):
         self.login_as(user=self.user)
@@ -328,3 +370,33 @@ class GroupListTest(APITestCase, SnubaTestCase):
             HTTP_AUTHORIZATION='Bearer %s' %
             token.token)
         assert response.status_code == 200, response.content
+
+    def test_date_range(self):
+        now = timezone.now()
+        with self.options({'system.event-retention-days': 2}):
+            group = self.create_group(
+                last_seen=now - timedelta(hours=5),
+                # first_seen needs to be accurate because of `shrink_time_window`
+                first_seen=now - timedelta(hours=5),
+                project=self.project,
+            )
+
+            self.create_event(
+                group=group,
+                datetime=now - timedelta(hours=5),
+            )
+            self.login_as(user=self.user)
+
+            response = self.client.get(
+                '%s?statsPeriod=6h' % (self.path,),
+                format='json',
+            )
+            assert len(response.data) == 1
+            assert response.data[0]['id'] == six.text_type(group.id)
+
+            response = self.client.get(
+                '%s?statsPeriod=1h' % (self.path,),
+                format='json',
+            )
+
+            assert len(response.data) == 0