Skip to content

Commit

Permalink
Make error.main_thread searchable on Discover and Issues page (#46183)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored and schew2381 committed Apr 12, 2023
1 parent 4bc77c5 commit 28d0da3
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/sentry/api/event_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,7 @@ def generic_visit(self, node, children):
boolean_keys={
"error.handled",
"error.unhandled",
"error.main_thread",
"stack.in_app",
TEAM_KEY_TRANSACTION_ALIAS,
},
Expand Down
9 changes: 9 additions & 0 deletions src/sentry/data/samples/android-ndk.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{
"type": "SIGSEGV",
"value": "Segfault",
"thread_id": 1,
"mechanism": {
"type": "signalhandler",
"synthetic": true,
Expand Down Expand Up @@ -132,6 +133,14 @@
}
]
},
"threads": {
"values": [
{
"id": 1,
"main": true
}
]
},
"platform": "native",
"debug_meta": {
"images": [
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/issues/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def _update_profiling_search_filters(
for sf in search_filters:
# XXX: we replace queries on these keys to something that should return nothing since
# profiling issues doesn't support stacktraces
if sf.key.name in ("error.unhandled", "error.handled"):
if sf.key.name in ("error.unhandled", "error.handled", "error.main_thread"):
raise UnsupportedSearchQuery(
f"{sf.key.name} filter isn't supported for {GroupCategory.PROFILE.name}"
)
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/rules/conditions/event_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"type": Columns.TYPE,
"error.handled": Columns.ERROR_HANDLED,
"error.unhandled": Columns.ERROR_HANDLED,
"error.main_thread": Columns.ERROR_MAIN_THREAD,
"exception.type": Columns.ERROR_TYPE,
"exception.value": Columns.ERROR_VALUE,
"user.id": Columns.USER_ID,
Expand Down Expand Up @@ -118,6 +119,8 @@ def _get_attribute_values(self, event: GroupEvent, attr: str) -> Sequence[str]:
return [getattr(e, path[1]) for e in event.interfaces["exception"].values]

elif path[0] == "error":
# TODO: add support for error.main_thread

if path[1] not in ("handled", "unhandled"):
return []

Expand Down
8 changes: 8 additions & 0 deletions src/sentry/snuba/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,14 @@ class Columns(Enum):
discover_name="exception_stacks.mechanism_handled",
alias="error.handled",
)
ERROR_MAIN_THREAD = Column(
group_name="events.exception_main_thread",
event_name="exception_main_thread",
transaction_name=None,
discover_name="exception_main_thread",
issue_platform_name=None,
alias="error.main_thread",
)
ERROR_RECEIVED = Column(
group_name=None,
event_name="received",
Expand Down
9 changes: 9 additions & 0 deletions tests/sentry/rules/conditions/test_event_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def get_event(self, **kwargs):
}
]
},
"thread_id": 1,
}
]
},
Expand All @@ -57,6 +58,14 @@ def get_event(self, **kwargs):
"crash_type": "crash",
},
},
"threads": {
"values": [
{
"id": 1,
"main": True,
},
],
},
}
data.update(kwargs)
event = self.store_event(data, project_id=self.project.id)
Expand Down
26 changes: 26 additions & 0 deletions tests/snuba/api/endpoints/test_organization_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,32 @@ def test_groupby_error_handled_and_unhandled(self):
assert 1 == response.data["data"][1]["error.unhandled"]
assert 1 == response.data["data"][1]["count()"]

def test_error_main_thread_condition(self):
prototype = self.load_data(platform="android-ndk")

prototype["timestamp"] = self.ten_mins_ago_iso
self.store_event(data=prototype, project_id=self.project.id)

with self.feature("organizations:discover-basic"):
query = {
"field": ["id", "project.id"],
"query": "error.main_thread:true",
"project": [self.project.id],
}
response = self.do_request(query)
assert response.status_code == 200, response.data
assert 1 == len(response.data["data"])

with self.feature("organizations:discover-basic"):
query = {
"field": ["id", "project.id"],
"query": "error.main_thread:false",
"project": [self.project.id],
}
response = self.do_request(query)
assert response.status_code == 200, response.data
assert 0 == len(response.data["data"])

def test_implicit_groupby(self):
self.store_event(
data={
Expand Down
146 changes: 145 additions & 1 deletion tests/snuba/search/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,126 @@ def test_message_negation(self):

assert list(results) == list(results2)

def test_error_main_thread_true(self):
myProject = self.create_project(
name="Foo", slug="foo", teams=[self.team], fire_project_created=True
)

event = self.store_event(
data={
"event_id": "1" * 32,
"message": "something",
"timestamp": iso_format(self.base_datetime),
"exception": {
"values": [
{
"type": "SyntaxError",
"value": "hello world",
"thread_id": 1,
},
],
},
"threads": {
"values": [
{
"id": 1,
"main": True,
},
],
},
},
project_id=myProject.id,
)

myGroup = event.groups[0]

results = self.make_query(
projects=[myProject],
search_filter_query="error.main_thread:1",
sort_by="date",
)

assert list(results) == [myGroup]

def test_error_main_thread_false(self):
myProject = self.create_project(
name="Foo2", slug="foo2", teams=[self.team], fire_project_created=True
)

event = self.store_event(
data={
"event_id": "2" * 32,
"message": "something",
"timestamp": iso_format(self.base_datetime),
"exception": {
"values": [
{
"type": "SyntaxError",
"value": "hello world",
"thread_id": 1,
},
],
},
"threads": {
"values": [
{
"id": 1,
"main": False,
},
],
},
},
project_id=myProject.id,
)

myGroup = event.groups[0]

results = self.make_query(
projects=[myProject],
search_filter_query="error.main_thread:0",
sort_by="date",
)

assert list(results) == [myGroup]

def test_error_main_thread_no_results(self):
myProject = self.create_project(
name="Foo3", slug="foo3", teams=[self.team], fire_project_created=True
)

self.store_event(
data={
"event_id": "3" * 32,
"message": "something",
"timestamp": iso_format(self.base_datetime),
"exception": {
"values": [
{
"type": "SyntaxError",
"value": "hello world",
"thread_id": 1,
},
],
},
"threads": {
"values": [
{
"id": 1,
},
],
},
},
project_id=myProject.id,
)

results = self.make_query(
projects=[myProject],
search_filter_query="error.main_thread:1",
sort_by="date",
)

assert len(results) == 0


class EventsTransactionsSnubaSearchTest(SharedSnubaTest):
@property
Expand Down Expand Up @@ -2507,7 +2627,31 @@ def test_rejected_filters(self):
count_hits=True,
)

assert list(results) == list(results2) == list(result3) == list(results4) == []
results5 = self.make_query(
projects=[self.project],
search_filter_query="issue.category:profile error.main_thread:0",
sort_by="date",
limit=1,
count_hits=True,
)

results6 = self.make_query(
projects=[self.project],
search_filter_query="issue.category:profile error.main_thread:1",
sort_by="date",
limit=1,
count_hits=True,
)

assert (
list(results)
== list(results2)
== list(result3)
== list(results4)
== list(results5)
== list(results6)
== []
)


class CdcEventsSnubaSearchTest(SharedSnubaTest):
Expand Down

0 comments on commit 28d0da3

Please sign in to comment.