Просмотр исходного кода

feat(cra-metrics): Replace UI autocomplete backend (#31280)

Replaces the autocomplete release tag values for
crash rate alerts backend with the Release model on
postgres
Ahmed Etefy 3 лет назад
Родитель
Сommit
c89a2cc78a

+ 1 - 0
src/sentry/api/endpoints/organization_tagkey_values.py

@@ -34,6 +34,7 @@ class OrganizationTagKeyValuesEndpoint(OrganizationEventsEndpointBase):
                     filter_params["end"],
                     query=request.GET.get("query"),
                     include_transactions=request.GET.get("includeTransactions") == "1",
+                    include_sessions=request.GET.get("includeSessions") == "1",
                 )
 
         return self.paginate(

+ 37 - 0
src/sentry/tagstore/snuba/backend.py

@@ -19,6 +19,7 @@ from sentry.models import (
 )
 from sentry.search.events.constants import (
     PROJECT_ALIAS,
+    RELEASE_ALIAS,
     RELEASE_STAGE_ALIAS,
     SEMVER_ALIAS,
     SEMVER_BUILD_ALIAS,
@@ -860,6 +861,36 @@ class SnubaTagStorage(TagStorage):
             [(i, TagValue(SEMVER_BUILD_ALIAS, v, None, None, None)) for i, v in enumerate(packages)]
         )
 
+    def _get_tag_values_for_releases_across_all_datasets(self, projects, environments, query):
+        from sentry.api.paginator import SequencePaginator
+
+        organization_id = Project.objects.filter(id=projects[0]).values_list(
+            "organization_id", flat=True
+        )[0]
+        qs = Release.objects.filter(organization_id=organization_id)
+
+        if projects:
+            qs = qs.filter(
+                id__in=ReleaseProject.objects.filter(project_id__in=projects).values_list(
+                    "release_id", flat=True
+                )
+            )
+        if environments:
+            qs = qs.filter(
+                id__in=ReleaseEnvironment.objects.filter(
+                    environment_id__in=environments
+                ).values_list("release_id", flat=True)
+            )
+
+        if query:
+            qs = qs.filter(version__startswith=query)
+
+        versions = qs.order_by("version").values_list("version", flat=True)[:1000]
+
+        return SequencePaginator(
+            [(i, TagValue(RELEASE_ALIAS, v, None, None, None)) for i, v in enumerate(versions)]
+        )
+
     def get_tag_value_paginator_for_projects(
         self,
         projects,
@@ -870,6 +901,7 @@ class SnubaTagStorage(TagStorage):
         query=None,
         order_by="-last_seen",
         include_transactions=False,
+        include_sessions=False,
     ):
         from sentry.api.paginator import SequencePaginator
 
@@ -940,6 +972,11 @@ class SnubaTagStorage(TagStorage):
         if key == SEMVER_BUILD_ALIAS:
             return self._get_tag_values_for_semver_build(projects, environments, query)
 
+        if key == RELEASE_ALIAS and include_sessions:
+            return self._get_tag_values_for_releases_across_all_datasets(
+                projects, environments, query
+            )
+
         conditions = []
         project_slugs = {}
         # transaction status needs a special case so that the user interacts with the names and not codes

+ 84 - 1
tests/snuba/api/endpoints/test_organization_tagkey_values.py

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.urls import reverse
 from exam import fixture
 
-from sentry.search.events.constants import SEMVER_ALIAS
+from sentry.search.events.constants import RELEASE_ALIAS, SEMVER_ALIAS
 from sentry.testutils import APITestCase, SnubaTestCase
 from sentry.testutils.helpers.datetime import before_now, iso_format
 from sentry.utils.samples import load_data
@@ -328,6 +328,89 @@ class OrganizationTagKeyValuesTest(OrganizationTagKeyTestCase):
             SEMVER_ALIAS, query="test", expected=[("test@2.0.0.0", None), ("test@1.0.0.0", None)]
         )
 
+    def test_release_filter_for_all_releases(self):
+        self.create_release(version="aaa@1.0")
+        self.create_release(version="aab@1.0")
+        self.create_release(version="aba@1.0")
+        self.create_release(version="abc@1.0")
+        self.create_release(version="bac@1.0")
+
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1"},
+            expected=[
+                ("aaa@1.0", None),
+                ("aab@1.0", None),
+                ("aba@1.0", None),
+                ("abc@1.0", None),
+                ("bac@1.0", None),
+            ],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1", "query": "a"},
+            expected=[("aaa@1.0", None), ("aab@1.0", None), ("aba@1.0", None), ("abc@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1", "query": "b"},
+            expected=[("bac@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1", "query": "aa"},
+            expected=[("aaa@1.0", None), ("aab@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1", "query": "aba"},
+            expected=[("aba@1.0", None)],
+        )
+
+    def test_release_filter_for_all_releases_with_env_and_project_filters(self):
+        proj2 = self.create_project()
+
+        env1 = self.create_environment(name="dev", project=self.project)
+        env2 = self.create_environment(name="prod", project=self.project)
+        env3 = self.create_environment(name="test", project=proj2)
+
+        self.create_release(version="aaa@1.0", environments=[env1, env2])
+        self.create_release(version="aab@1.0", environments=[env1])
+        self.create_release(version="aba@1.0", project=proj2, environments=[env3])
+
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={"includeSessions": "1", "project": [self.project.id]},
+            expected=[("aaa@1.0", None), ("aab@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={
+                "includeSessions": "1",
+                "project": [self.project.id],
+                "environment": [env1.name],
+            },
+            expected=[("aaa@1.0", None), ("aab@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={
+                "includeSessions": "1",
+                "project": [self.project.id],
+                "environment": [env2.name],
+            },
+            expected=[("aaa@1.0", None)],
+        )
+        self.run_test(
+            RELEASE_ALIAS,
+            qs_params={
+                "includeSessions": "1",
+                "project": [self.project.id, proj2.id],
+                "environment": [env2.name, env3.name],
+            },
+            expected=[("aaa@1.0", None), ("aba@1.0", None)],
+        )
+
 
 class TransactionTagKeyValues(OrganizationTagKeyTestCase):
     def setUp(self):