Skip to content

Commit e5c4f12

Browse files
committed
move event_content_is_seer_eligible to ingest seer module
1 parent 1e59e13 commit e5c4f12

File tree

5 files changed

+103
-104
lines changed

5 files changed

+103
-104
lines changed

src/sentry/grouping/ingest/seer.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
from sentry import options
1010
from sentry import ratelimits as ratelimiter
1111
from sentry.conf.server import SEER_SIMILARITY_MODEL_VERSION
12-
from sentry.eventstore.models import Event
12+
from sentry.eventstore.models import Event, GroupEvent
1313
from sentry.grouping.grouping_info import get_grouping_info_from_variants
1414
from sentry.grouping.variants import BaseVariant
1515
from sentry.models.grouphash import GroupHash
1616
from sentry.models.project import Project
1717
from sentry.seer.similarity.similar_issues import get_similarity_data_from_seer
1818
from sentry.seer.similarity.types import SimilarIssuesEmbeddingsRequest
1919
from sentry.seer.similarity.utils import (
20+
SEER_INELIGIBLE_EVENT_PLATFORMS,
2021
ReferrerOptions,
21-
event_content_is_seer_eligible,
22+
event_content_has_stacktrace,
2223
filter_null_from_string,
2324
get_stacktrace_string_with_metrics,
2425
killswitch_enabled,
@@ -40,7 +41,7 @@ def should_call_seer_for_grouping(event: Event, variants: Mapping[str, BaseVaria
4041
project = event.project
4142

4243
# Check both of these before returning based on either so we can gather metrics on their results
43-
content_is_eligible = event_content_is_seer_eligible(event)
44+
content_is_eligible = _event_content_is_seer_eligible(event)
4445
seer_enabled_for_project = _project_has_similarity_grouping_enabled(project)
4546
if not (content_is_eligible and seer_enabled_for_project):
4647
return False
@@ -67,6 +68,34 @@ def should_call_seer_for_grouping(event: Event, variants: Mapping[str, BaseVaria
6768
return True
6869

6970

71+
def _event_content_is_seer_eligible(event: GroupEvent | Event) -> bool:
72+
"""
73+
Determine if an event's contents makes it fit for using with Seer's similar issues model.
74+
"""
75+
if not event_content_has_stacktrace(event):
76+
metrics.incr(
77+
"grouping.similarity.event_content_seer_eligible",
78+
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
79+
tags={"eligible": False, "blocker": "no-stacktrace"},
80+
)
81+
return False
82+
83+
if event.platform in SEER_INELIGIBLE_EVENT_PLATFORMS:
84+
metrics.incr(
85+
"grouping.similarity.event_content_seer_eligible",
86+
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
87+
tags={"eligible": False, "blocker": "unsupported-platform"},
88+
)
89+
return False
90+
91+
metrics.incr(
92+
"grouping.similarity.event_content_seer_eligible",
93+
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
94+
tags={"eligible": True, "blocker": "none"},
95+
)
96+
return True
97+
98+
7099
def _project_has_similarity_grouping_enabled(project: Project) -> bool:
71100
# TODO: This is a hack to get ingest to turn on for projects as soon as they're backfilled. When
72101
# the backfill script completes, we turn on this option, enabling ingest immediately rather than

src/sentry/seer/similarity/utils.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -319,35 +319,6 @@ def event_content_has_stacktrace(event: GroupEvent | Event) -> bool:
319319
return exception_stacktrace or threads_stacktrace or only_stacktrace
320320

321321

322-
def event_content_is_seer_eligible(event: GroupEvent | Event) -> bool:
323-
"""
324-
Determine if an event's contents makes it fit for using with Seer's similar issues model.
325-
"""
326-
# TODO: Determine if we want to filter out non-sourcemapped events
327-
if not event_content_has_stacktrace(event):
328-
metrics.incr(
329-
"grouping.similarity.event_content_seer_eligible",
330-
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
331-
tags={"eligible": False, "blocker": "no-stacktrace"},
332-
)
333-
return False
334-
335-
if event.platform in SEER_INELIGIBLE_EVENT_PLATFORMS:
336-
metrics.incr(
337-
"grouping.similarity.event_content_seer_eligible",
338-
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
339-
tags={"eligible": False, "blocker": "unsupported-platform"},
340-
)
341-
return False
342-
343-
metrics.incr(
344-
"grouping.similarity.event_content_seer_eligible",
345-
sample_rate=options.get("seer.similarity.metrics_sample_rate"),
346-
tags={"eligible": True, "blocker": "none"},
347-
)
348-
return True
349-
350-
351322
def record_did_call_seer_metric(*, call_made: bool, blocker: str) -> None:
352323
metrics.incr(
353324
"grouping.similarity.did_call_seer",

tests/sentry/event_manager/grouping/test_seer_grouping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_obeys_seer_similarity_flags(self):
6767
return_value=[seer_result_data],
6868
),
6969
patch(
70-
"sentry.grouping.ingest.seer.event_content_is_seer_eligible",
70+
"sentry.grouping.ingest.seer._event_content_is_seer_eligible",
7171
return_value=True,
7272
),
7373
):

tests/sentry/grouping/ingest/test_seer.py

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
from dataclasses import asdict
22
from time import time
3+
from typing import Any
34
from unittest.mock import ANY, MagicMock, Mock, call, patch
5+
from uuid import uuid1
46

57
from sentry import options
68
from sentry.conf.server import SEER_SIMILARITY_MODEL_VERSION
79
from sentry.eventstore.models import Event
810
from sentry.grouping.ingest.seer import (
11+
_event_content_is_seer_eligible,
912
get_seer_similar_issues,
1013
maybe_check_seer_for_matching_grouphash,
1114
should_call_seer_for_grouping,
1215
)
1316
from sentry.models.grouphash import GroupHash
1417
from sentry.seer.similarity.types import SeerSimilarIssueData
15-
from sentry.seer.similarity.utils import MAX_FRAME_COUNT
18+
from sentry.seer.similarity.utils import MAX_FRAME_COUNT, SEER_INELIGIBLE_EVENT_PLATFORMS
1619
from sentry.testutils.cases import TestCase
1720
from sentry.testutils.helpers.eventprocessing import save_new_event
1821
from sentry.testutils.helpers.options import override_options
@@ -65,7 +68,7 @@ def test_obeys_content_filter(self) -> None:
6568

6669
for content_eligibility, expected_result in [(True, True), (False, False)]:
6770
with patch(
68-
"sentry.grouping.ingest.seer.event_content_is_seer_eligible",
71+
"sentry.grouping.ingest.seer._event_content_is_seer_eligible",
6972
return_value=content_eligibility,
7073
):
7174
assert should_call_seer_for_grouping(self.event, self.variants) is expected_result
@@ -603,3 +606,68 @@ def test_too_many_only_system_frames_maybe_check_seer_for_matching_group_hash_in
603606
"use_reranking": True,
604607
}
605608
)
609+
610+
611+
class EventContentIsSeerEligibleTest(TestCase):
612+
def get_eligible_event_data(self) -> dict[str, Any]:
613+
return {
614+
"title": "FailedToFetchError('Charlie didn't bring the ball back')",
615+
"exception": {
616+
"values": [
617+
{
618+
"type": "FailedToFetchError",
619+
"value": "Charlie didn't bring the ball back",
620+
"stacktrace": {
621+
"frames": [
622+
{
623+
"function": "play_fetch",
624+
"filename": "dogpark.py",
625+
"context_line": "raise FailedToFetchError('Charlie didn't bring the ball back')",
626+
}
627+
]
628+
},
629+
}
630+
]
631+
},
632+
"platform": "python",
633+
}
634+
635+
def test_no_stacktrace(self):
636+
good_event_data = self.get_eligible_event_data()
637+
good_event = Event(
638+
project_id=self.project.id,
639+
event_id=uuid1().hex,
640+
data=good_event_data,
641+
)
642+
643+
bad_event_data = self.get_eligible_event_data()
644+
del bad_event_data["exception"]
645+
bad_event = Event(
646+
project_id=self.project.id,
647+
event_id=uuid1().hex,
648+
data=bad_event_data,
649+
)
650+
651+
assert _event_content_is_seer_eligible(good_event) is True
652+
assert _event_content_is_seer_eligible(bad_event) is False
653+
654+
def test_platform_filter(self):
655+
good_event_data = self.get_eligible_event_data()
656+
good_event = Event(
657+
project_id=self.project.id,
658+
event_id=uuid1().hex,
659+
data=good_event_data,
660+
)
661+
662+
bad_event_data = self.get_eligible_event_data()
663+
bad_event_data["platform"] = "other"
664+
bad_event = Event(
665+
project_id=self.project.id,
666+
event_id=uuid1().hex,
667+
data=bad_event_data,
668+
)
669+
670+
assert good_event_data["platform"] not in SEER_INELIGIBLE_EVENT_PLATFORMS
671+
assert bad_event_data["platform"] in SEER_INELIGIBLE_EVENT_PLATFORMS
672+
assert _event_content_is_seer_eligible(good_event) is True
673+
assert _event_content_is_seer_eligible(bad_event) is False

tests/sentry/seer/similarity/test_utils.py

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,15 @@
22
from collections.abc import Callable
33
from typing import Any, Literal, cast
44
from unittest.mock import patch
5-
from uuid import uuid1
65

76
import pytest
87

9-
from sentry.eventstore.models import Event
108
from sentry.seer.similarity.utils import (
119
BASE64_ENCODED_PREFIXES,
1210
MAX_FRAME_COUNT,
13-
SEER_INELIGIBLE_EVENT_PLATFORMS,
1411
ReferrerOptions,
1512
TooManyOnlySystemFramesException,
1613
_is_snipped_context_line,
17-
event_content_is_seer_eligible,
1814
filter_null_from_string,
1915
get_stacktrace_string,
2016
get_stacktrace_string_with_metrics,
@@ -875,71 +871,6 @@ def test_no_header_one_frame_no_filename(self, mock_metrics):
875871
assert get_stacktrace_string(exception) == ""
876872

877873

878-
class EventContentIsSeerEligibleTest(TestCase):
879-
def get_eligible_event_data(self) -> dict[str, Any]:
880-
return {
881-
"title": "FailedToFetchError('Charlie didn't bring the ball back')",
882-
"exception": {
883-
"values": [
884-
{
885-
"type": "FailedToFetchError",
886-
"value": "Charlie didn't bring the ball back",
887-
"stacktrace": {
888-
"frames": [
889-
{
890-
"function": "play_fetch",
891-
"filename": "dogpark.py",
892-
"context_line": "raise FailedToFetchError('Charlie didn't bring the ball back')",
893-
}
894-
]
895-
},
896-
}
897-
]
898-
},
899-
"platform": "python",
900-
}
901-
902-
def test_no_stacktrace(self):
903-
good_event_data = self.get_eligible_event_data()
904-
good_event = Event(
905-
project_id=self.project.id,
906-
event_id=uuid1().hex,
907-
data=good_event_data,
908-
)
909-
910-
bad_event_data = self.get_eligible_event_data()
911-
del bad_event_data["exception"]
912-
bad_event = Event(
913-
project_id=self.project.id,
914-
event_id=uuid1().hex,
915-
data=bad_event_data,
916-
)
917-
918-
assert event_content_is_seer_eligible(good_event) is True
919-
assert event_content_is_seer_eligible(bad_event) is False
920-
921-
def test_platform_filter(self):
922-
good_event_data = self.get_eligible_event_data()
923-
good_event = Event(
924-
project_id=self.project.id,
925-
event_id=uuid1().hex,
926-
data=good_event_data,
927-
)
928-
929-
bad_event_data = self.get_eligible_event_data()
930-
bad_event_data["platform"] = "other"
931-
bad_event = Event(
932-
project_id=self.project.id,
933-
event_id=uuid1().hex,
934-
data=bad_event_data,
935-
)
936-
937-
assert good_event_data["platform"] not in SEER_INELIGIBLE_EVENT_PLATFORMS
938-
assert bad_event_data["platform"] in SEER_INELIGIBLE_EVENT_PLATFORMS
939-
assert event_content_is_seer_eligible(good_event) is True
940-
assert event_content_is_seer_eligible(bad_event) is False
941-
942-
943874
class SeerUtilsTest(TestCase):
944875
def test_filter_null_from_string(self):
945876
string_with_null = 'String with null \x00, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" is null'

0 commit comments

Comments
 (0)