Browse Source

feat(alert): Add stacktrace.abs_path as an alerting option #20814

Some customers would like to be able to filter away alerts from third party libraries. This seems to be most easily distinguished by keywords in the absolute path of the stacktrace. This code exposes abs_path as a possible alerting option for the EventAttributeCondition.
David Wang 4 years ago
parent
commit
3c80d31236

+ 3 - 3
src/sentry/rules/conditions/event_attribute.py

@@ -48,6 +48,7 @@ ATTR_CHOICES = [
     "stacktrace.code",
     "stacktrace.module",
     "stacktrace.filename",
+    "stacktrace.abs_path",
 ]
 
 
@@ -68,7 +69,7 @@ class EventAttributeCondition(EventCondition):
     - exception.{type,value}
     - user.{id,ip_address,email,FIELD}
     - http.{method,url}
-    - stacktrace.{code,module,filename}
+    - stacktrace.{code,module,filename,abs_path}
     - extra.{FIELD}
     """
 
@@ -150,11 +151,10 @@ class EventAttributeCondition(EventCondition):
                 stacks = [
                     e.stacktrace for e in event.interfaces["exception"].values if e.stacktrace
                 ]
-
             result = []
             for st in stacks:
                 for frame in st.frames:
-                    if path[1] in ("filename", "module"):
+                    if path[1] in ("filename", "module", "abs_path"):
                         result.append(getattr(frame, path[1]))
                     elif path[1] == "code":
                         if frame.pre_context:

+ 51 - 0
tests/sentry/rules/conditions/test_event_attribute.py

@@ -28,6 +28,7 @@ class EventAttributeConditionTest(RuleTestCase):
                                     "filename": "example.php",
                                     "module": "example",
                                     "context_line": 'echo "hello";',
+                                    "abs_path": "path/to/example.php",
                                 }
                             ]
                         },
@@ -412,3 +413,53 @@ class EventAttributeConditionTest(RuleTestCase):
 
         rule = self.get_rule(data={"match": MatchType.EQUAL, "attribute": "type", "value": "csp"})
         self.assertDoesNotPass(rule, event)
+
+    def test_stacktrace_abs_path(self):
+        """Stacktrace.abs_path should match frames anywhere in the stack."""
+
+        event = self.get_event(
+            exception={
+                "values": [
+                    {
+                        "type": "SyntaxError",
+                        "value": "hello world",
+                        "stacktrace": {
+                            "frames": [
+                                {
+                                    "filename": "example.php",
+                                    "module": "example",
+                                    "abs_path": "path/to/example.php",
+                                },
+                                {
+                                    "filename": "somecode.php",
+                                    "module": "somecode",
+                                    "abs_path": "path/to/somecode.php",
+                                },
+                                {
+                                    "filename": "othercode.php",
+                                    "module": "othercode",
+                                    "abs_path": "path/to/othercode.php",
+                                },
+                            ]
+                        },
+                    }
+                ]
+            }
+        )
+
+        # correctly matching filenames, at various locations in the stacktrace
+        for value in ["path/to/example.php", "path/to/somecode.php", "path/to/othercode.php"]:
+            rule = self.get_rule(
+                data={"match": MatchType.EQUAL, "attribute": "stacktrace.abs_path", "value": value}
+            )
+            self.assertPasses(rule, event)
+
+        # non-matching filename
+        rule = self.get_rule(
+            data={
+                "match": MatchType.EQUAL,
+                "attribute": "stacktrace.abs_path",
+                "value": "path/to/foo.php",
+            }
+        )
+        self.assertDoesNotPass(rule, event)