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

fix(search) Make error.handled conditions use new functions (#20688)

Update condition generation for error.handled field to use the new
functions available in snuba. This enables the `error.handled:0`
condition to work the way users are expecting it to.
Mark Story 4 лет назад
Родитель
Сommit
c3081cfbfe

+ 13 - 0
src/sentry/api/event_search.py

@@ -794,6 +794,19 @@ def convert_search_filter_to_snuba_query(search_filter, key=None):
                 1,
             ]
         return [user_display_expr, search_filter.operator, value]
+    elif name == "error.handled":
+        # Treat has filter as equivalent to handled
+        if search_filter.value.raw_value == "":
+            output = 1 if search_filter.operator == "!=" else 0
+            return [["isHandled", []], "=", output]
+        # Null values and 1 are the same, and both indicate a handled error.
+        if value in ("1", 1):
+            return [["isHandled", []], "=", 1]
+        if value in ("0", 0,):
+            return [["notHandled", []], "=", 1]
+        raise InvalidSearchQuery(
+            "Invalid value for error.handled condition. Accepted values are 1, 0"
+        )
     else:
         value = (
             int(to_timestamp(value)) * 1000

+ 23 - 0
tests/sentry/api/test_event_search.py

@@ -1650,6 +1650,29 @@ class GetSnubaQueryArgsTest(TestCase):
         assert "Invalid value" in six.text_type(err)
         assert "cancelled," in six.text_type(err)
 
+    def test_error_handled(self):
+        result = get_filter("error.handled:1")
+        assert result.conditions == [[["isHandled", []], "=", 1]]
+
+        result = get_filter("error.handled:0")
+        assert result.conditions == [[["notHandled", []], "=", 1]]
+
+        result = get_filter("has:error.handled")
+        assert result.conditions == [[["isHandled", []], "=", 1]]
+
+        result = get_filter("!has:error.handled")
+        assert result.conditions == [[["isHandled", []], "=", 0]]
+
+        with pytest.raises(InvalidSearchQuery):
+            get_filter("error.handled:99")
+
+        # Numeric fields can't be negated.
+        with pytest.raises(InvalidSearchQuery):
+            get_filter("!error.handled:0")
+
+        with pytest.raises(InvalidSearchQuery):
+            get_filter("!error.handled:1")
+
     def test_function_negation(self):
         result = get_filter("!p95():5s")
         assert result.having == [["p95", "!=", 5000.0]]

+ 40 - 0
tests/snuba/api/endpoints/test_organization_events_v2.py

@@ -492,6 +492,46 @@ class OrganizationEventsV2EndpointTest(APITestCase, SnubaTestCase):
         assert response.data["data"][0]["project"] == project2.slug
         assert "project.id" not in response.data["data"][0]
 
+    def test_error_handled_condition(self):
+        self.login_as(user=self.user)
+        project = self.create_project()
+        prototype = load_data("android-ndk")
+        events = (
+            ("a" * 32, "not handled", False),
+            ("b" * 32, "was handled", True),
+            ("c" * 32, "undefined", None),
+        )
+        for event in events:
+            prototype["event_id"] = event[0]
+            prototype["message"] = event[1]
+            prototype["exception"]["values"][0]["value"] = event[1]
+            prototype["exception"]["values"][0]["mechanism"]["handled"] = event[2]
+            prototype["timestamp"] = self.two_min_ago
+            self.store_event(data=prototype, project_id=project.id)
+
+        with self.feature("organizations:discover-basic"):
+            query = {
+                "field": ["message", "error.handled"],
+                "query": "error.handled:0",
+                "orderby": "message",
+            }
+            response = self.do_request(query)
+            assert response.status_code == 200
+            assert 1 == len(response.data["data"])
+            assert [0] == response.data["data"][0]["error.handled"]
+
+        with self.feature("organizations:discover-basic"):
+            query = {
+                "field": ["message", "error.handled"],
+                "query": "error.handled:1",
+                "orderby": "message",
+            }
+            response = self.do_request(query)
+            assert response.status_code == 200, response.data
+            assert 2 == len(response.data["data"])
+            assert [None] == response.data["data"][0]["error.handled"]
+            assert [1] == response.data["data"][1]["error.handled"]
+
     def test_implicit_groupby(self):
         project = self.create_project()
         self.store_event(

+ 3 - 1
tests/snuba/search/test_backend.py

@@ -1418,7 +1418,9 @@ class EventsSnubaSearchTest(TestCase, SnubaTestCase):
                 continue
             test_query("has:%s" % key)
             test_query("!has:%s" % key)
-            if key in IssueSearchVisitor.numeric_keys:
+            if key == "error.handled":
+                val = 1
+            elif key in IssueSearchVisitor.numeric_keys:
                 val = "123"
             elif key in IssueSearchVisitor.date_keys:
                 val = "2019-01-01"