Skip to content

Commit cf476ea

Browse files
authored
ref(grouping): Skip exception filtering for new Python SDK events (#95272)
The new version of the Python SDK (version 3) sends `mechanism` data with exceptions which the old version didn't used to. As a result, certain exception groups are hashing differently because they can now use the `filter_exceptions_for_exception_groups` helper in the newstyle grouping config. In the long run, we need to figure out how to compensate for this on the server side, so that we can match up old hashes with new hashes. In the short run, in order not to block the release of the SDK, we're just going to pretend the change didn't happen, by bailing out of the helper early for events from the new version of the SDK.
1 parent f694d56 commit cf476ea

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/sentry/grouping/strategies/newstyle.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from sentry.interfaces.stacktrace import Frame, Stacktrace
3636
from sentry.interfaces.threads import Threads
3737
from sentry.stacktraces.platform import get_behavior_family_for_platform
38+
from sentry.utils.safe import get_path
3839

3940
if TYPE_CHECKING:
4041
from sentry.eventstore.models import Event
@@ -679,6 +680,17 @@ def filter_exceptions_for_exception_groups(
679680
if len(exceptions) <= 1:
680681
return exceptions
681682

683+
# TODO: Get rid of this hack!
684+
#
685+
# A change in the python SDK between version 2 and version 3 means that suddenly this function
686+
# applies where it didn't used to, which in turn changes how some exception groups are hashed.
687+
# As a temporary stopgap, until we can build a system akin to the grouping config transition
688+
# system to compensate for the change, we're just emulating the old behavior.
689+
if event.platform == "python" and get_path(event.data, "sdk", "version", default="").startswith(
690+
"3"
691+
):
692+
return exceptions
693+
682694
# Reconstruct the tree of exceptions if the required data is present.
683695
class ExceptionTreeNode:
684696
def __init__(
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from typing import Any
2+
3+
from sentry.eventstore.models import Event
4+
from sentry.testutils.cases import TestCase
5+
6+
7+
class ChainedExceptionTest(TestCase):
8+
def test_ignores_mechanism_in_python_sdk_version_3_chained_exception_events(self):
9+
# First, get hashes for an event with no `mechanism` data
10+
event_data: dict[str, Any] = {
11+
"platform": "python",
12+
"sdk": {"name": "python", "version": "3.1"},
13+
"exception": {
14+
"values": [
15+
{"type": "FetchError", "value": "Charlie didn't bring the ball back"},
16+
{"type": "ShoeError", "value": "Oh, no! Charlie ate the flip-flops!"},
17+
{"type": "AggregateException", "value": "She's a very good dog, but..."},
18+
]
19+
},
20+
}
21+
22+
no_mechanism_hashes = Event(
23+
event_id="1121123104150908",
24+
project_id=self.project.id,
25+
data=event_data,
26+
).get_hashes()
27+
28+
# Now add in `mechanism` data, and we'll see that the hash doesn't change
29+
event_data["exception"]["values"][0]["mechanism"] = {
30+
"type": "chained",
31+
"handled": True,
32+
"source": "InnerExceptions[1]",
33+
"exception_id": 2,
34+
"parent_id": 0,
35+
}
36+
event_data["exception"]["values"][1]["mechanism"] = {
37+
"type": "chained",
38+
"handled": True,
39+
"source": "InnerExceptions[0]",
40+
"exception_id": 1,
41+
"parent_id": 0,
42+
}
43+
event_data["exception"]["values"][2]["mechanism"] = {
44+
"type": "AppDomain.UnhandledException",
45+
"handled": False,
46+
"is_exception_group": True,
47+
"exception_id": 0,
48+
}
49+
50+
with_mechanism_hashes = Event(
51+
event_id="1231112109080415",
52+
project_id=self.project.id,
53+
data=event_data,
54+
).get_hashes()
55+
56+
assert no_mechanism_hashes == with_mechanism_hashes
57+
58+
# Just to prove that were it not for the hack, the grouping *would* change with the addition
59+
# of mechanism data, we switch the platform
60+
event_data["platform"] = "javascript"
61+
62+
js_with_mechanism_hashes = Event(
63+
event_id="1121201212312012",
64+
project_id=self.project.id,
65+
data=event_data,
66+
).get_hashes()
67+
68+
assert js_with_mechanism_hashes != no_mechanism_hashes

0 commit comments

Comments
 (0)