Browse Source

If Stacktrace interface is used for hashing, also use the Message interface if possible. (#5428)

Brett Hoerner 7 years ago
parent
commit
bda469fc8d
2 changed files with 39 additions and 0 deletions
  1. 11 0
      src/sentry/event_manager.py
  2. 28 0
      tests/sentry/test_event_manager.py

+ 11 - 0
src/sentry/event_manager.py

@@ -86,6 +86,17 @@ def get_hashes_for_event_with_reason(event):
         result = interface.compute_hashes(event.platform)
         if not result:
             continue
+
+        # HACK: if the top scoring interface is stacktrace then we also use the
+        # message interface so that events with the same stacktrace but differing
+        # messages will not be grouped, which is common if a single method can
+        # cause multiple separate error messages (that don't have exceptions attached).
+        message_key = 'sentry.interfaces.Message'
+        if interface.get_slug() == 'stacktrace' and message_key in interfaces:
+            message_hash = interfaces.get(message_key).compute_hashes(event.platform)
+            if message_hash:
+                result[0] = message_hash[0] + result[0]
+
         return (interface.get_path(), result)
     return ('message', [event.message])
 

+ 28 - 0
tests/sentry/test_event_manager.py

@@ -790,6 +790,34 @@ class GetHashesFromEventTest(TestCase):
         assert not http_comp_hash.called
         assert hash_one == ['foo', 'bar']
 
+    @patch('sentry.interfaces.stacktrace.Stacktrace.compute_hashes')
+    @patch('sentry.interfaces.message.Message.compute_hashes')
+    def test_stacktrace_hash_also_includes_message(self, message_comp_hash, stack_comp_hash):
+        # this tests the temporary hack in get_hashes_for_event_with_reason
+        message_comp_hash.return_value = [['baz']]
+        stack_comp_hash.return_value = [['foo', 'bar']]
+        event = Event(
+            data={
+                'sentry.interfaces.Stacktrace': {
+                    'frames': [{
+                        'lineno': 1,
+                        'filename': 'foo.py',
+                    }],
+                },
+                'sentry.interfaces.Message': {
+                    'message': 'abc'
+                },
+            },
+            platform='python',
+            message='Foo bar',
+        )
+        hashes = get_hashes_for_event(event)
+        assert len(hashes) == 1
+        hash_one = hashes[0]
+        stack_comp_hash.assert_called_once_with('python')
+        message_comp_hash.assert_called_once_with('python')
+        assert hash_one == ['baz', 'foo', 'bar']
+
 
 class GetHashesFromFingerprintTest(TestCase):
     def test_default_value(self):