Browse Source

feat(workflow): Add sort by count to tag values endpoint (#27696)

Scott Cooper 3 years ago
parent
commit
780f332472

+ 2 - 0
src/sentry/api/endpoints/group_tagkey_values.py

@@ -34,6 +34,8 @@ class GroupTagKeyValuesEndpoint(GroupEndpoint, EnvironmentMixin):
             order_by = "-last_seen"
         elif sort == "age":
             order_by = "-first_seen"
+        elif sort == "count":
+            order_by = "-times_seen"
         else:
             order_by = "-id"
 

+ 7 - 1
src/sentry/tagstore/snuba/backend.py

@@ -1081,7 +1081,7 @@ class SnubaTagStorage(TagStorage):
     ):
         from sentry.api.paginator import SequencePaginator
 
-        if order_by in ("-last_seen", "-first_seen"):
+        if order_by in ("-last_seen", "-first_seen", "-times_seen"):
             pass
         elif order_by == "-id":
             # Snuba has no unique id per GroupTagValue so we'll substitute `-first_seen`
@@ -1093,6 +1093,12 @@ class SnubaTagStorage(TagStorage):
 
         desc = order_by.startswith("-")
         score_field = order_by.lstrip("-")
+        if score_field == "times_seen":
+            return SequencePaginator(
+                [(int(getattr(gtv, score_field)), gtv) for gtv in group_tag_values],
+                reverse=desc,
+            )
+
         return SequencePaginator(
             [
                 (int(to_timestamp(getattr(gtv, score_field)) * 1000), gtv)

+ 61 - 0
tests/sentry/api/endpoints/test_group_tagkey_values.py

@@ -52,3 +52,64 @@ class GroupTagKeyValuesTest(APITestCase, SnubaTestCase):
 
         assert response.data[0]["email"] == "foo@example.com"
         assert response.data[0]["value"] == "id:1"
+
+    def test_count_sort(self):
+        project = self.create_project()
+        event = self.store_event(
+            data={
+                "message": "message 1",
+                "platform": "python",
+                "user": {
+                    "id": 1,
+                    "email": "foo@example.com",
+                    "username": "foo",
+                    "ip_address": "127.0.0.1",
+                },
+                "timestamp": iso_format(before_now(seconds=1)),
+            },
+            project_id=project.id,
+        )
+        self.store_event(
+            data={
+                "message": "message 1",
+                "platform": "python",
+                "user": {
+                    "id": 1,
+                    "email": "foo@example.com",
+                    "username": "foo",
+                    "ip_address": "127.0.0.1",
+                },
+                "timestamp": iso_format(before_now(seconds=1)),
+            },
+            project_id=project.id,
+        )
+        self.store_event(
+            data={
+                "message": "message 1",
+                "platform": "python",
+                "user": {
+                    "id": 2,
+                    "email": "bar@example.com",
+                    "username": "bar",
+                    "ip_address": "127.0.0.1",
+                },
+                "timestamp": iso_format(before_now(seconds=1)),
+            },
+            project_id=project.id,
+        )
+        group = event.group
+
+        self.login_as(user=self.user)
+
+        url = f"/api/0/issues/{group.id}/tags/user/values/?sort=count"
+
+        response = self.client.get(url)
+
+        assert response.status_code == 200
+        assert len(response.data) == 2
+
+        assert response.data[0]["email"] == "foo@example.com"
+        assert response.data[0]["value"] == "id:1"
+
+        assert response.data[1]["email"] == "bar@example.com"
+        assert response.data[1]["value"] == "id:2"

+ 70 - 20
tests/snuba/tagstore/test_tagstore_backend.py

@@ -21,6 +21,26 @@ from sentry.tagstore.types import TagValue
 from sentry.testutils import SnubaTestCase, TestCase
 from sentry.testutils.helpers.datetime import iso_format
 
+exception = {
+    "values": [
+        {
+            "type": "ValidationError",
+            "value": "Bad request",
+            "stacktrace": {
+                "frames": [
+                    {
+                        "function": "?",
+                        "filename": "http://localhost:1337/error.js",
+                        "lineno": 29,
+                        "colno": 3,
+                        "in_app": False,
+                    }
+                ]
+            },
+        }
+    ]
+}
+
 
 class TagStorageTest(TestCase, SnubaTestCase):
     def setUp(self):
@@ -36,26 +56,6 @@ class TagStorageTest(TestCase, SnubaTestCase):
         )
         self.now = timezone.now().replace(microsecond=0)
 
-        exception = {
-            "values": [
-                {
-                    "type": "ValidationError",
-                    "value": "Bad request",
-                    "stacktrace": {
-                        "frames": [
-                            {
-                                "function": "?",
-                                "filename": "http://localhost:1337/error.js",
-                                "lineno": 29,
-                                "colno": 3,
-                                "in_app": False,
-                            }
-                        ]
-                    },
-                }
-            ]
-        }
-
         self.store_event(
             data={
                 "event_id": "1" * 32,
@@ -666,6 +666,56 @@ class TagStorageTest(TestCase, SnubaTestCase):
             ),
         ]
 
+    def test_get_group_tag_value_paginator_times_seen(self):
+        from sentry.tagstore.types import GroupTagValue
+
+        self.store_event(
+            data={
+                "event_id": "5" * 32,
+                "message": "message 1",
+                "platform": "python",
+                "environment": self.proj1env1.name,
+                "fingerprint": ["group-1"],
+                "timestamp": iso_format(self.now - timedelta(seconds=2)),
+                "tags": {
+                    "foo": "bar",
+                    "baz": "quux",
+                    "sentry:release": 100,
+                    "sentry:user": "id:user2",
+                },
+                "user": {"id": "user2"},
+                "exception": exception,
+            },
+            project_id=self.proj1.id,
+        )
+
+        assert list(
+            self.ts.get_group_tag_value_paginator(
+                self.proj1.id,
+                self.proj1group1.id,
+                [self.proj1env1.id],
+                "sentry:user",
+                order_by="-times_seen",
+            ).get_result(10)
+        ) == [
+            GroupTagValue(
+                group_id=self.proj1group1.id,
+                key="sentry:user",
+                value="id:user2",
+                times_seen=2,
+                first_seen=self.now - timedelta(seconds=2),
+                last_seen=self.now - timedelta(seconds=2),
+            ),
+            GroupTagValue(
+                group_id=self.proj1group1.id,
+                key="sentry:user",
+                value="id:user1",
+                times_seen=1,
+                first_seen=self.now - timedelta(seconds=1),
+                last_seen=self.now - timedelta(seconds=1),
+            ),
+        ]
+
     def test_get_group_seen_values_for_environments(self):
         assert self.ts.get_group_seen_values_for_environments(
             [self.proj1.id], [self.proj1group1.id], [self.proj1env1.id]