Browse Source

ref(issue-platform): Cleanup occurrence processing in tests (#62984)

Abstract away some of the occurrence creation/processing logic to
provide a simpler way to create an occurrence. The basic usecase should
be able to call
`occurrence, group_info = self.process_occurrence(event_id='someid',
project_id=self.project.id)`
and not worry about the implementations of building the occurrence with
valid fields. Any additional occurrence data can be passed as kwargs,
and event data as a dict.

Fixes https://github.com/getsentry/sentry/issues/62504
Snigdha Sharma 1 year ago
parent
commit
f1830a7394

+ 4 - 9
tests/sentry/api/endpoints/test_group_event_details.py

@@ -1,7 +1,6 @@
 import uuid
 from uuid import uuid4
 
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.group import GroupStatus
 from sentry.models.release import Release
 from sentry.search.events.constants import SEMVER_ALIAS
@@ -379,14 +378,10 @@ class GroupEventDetailsHelpfulEndpointTest(
 
     def test_query_issue_platform_title(self):
         issue_title = "king of england"
-        occurrence_data = self.build_occurrence_data(project_id=self.project.id, title=issue_title)
-        occurrence, group_info = process_event_and_issue_occurrence(
-            occurrence_data,
-            event_data={
-                "event_id": occurrence_data["event_id"],
-                "project_id": occurrence_data["project_id"],
-                "level": "info",
-            },
+        occurrence, group_info = self.process_occurrence(
+            project_id=self.project.id,
+            title=issue_title,
+            event_data={"level": "info"},
         )
 
         assert group_info is not None

+ 5 - 11
tests/sentry/eventstore/test_models.py

@@ -8,7 +8,6 @@ from sentry.db.models.fields.node import NodeData, NodeIntegrityFailure
 from sentry.eventstore.models import Event, GroupEvent
 from sentry.grouping.enhancer import Enhancements
 from sentry.issues.issue_occurrence import IssueOccurrence
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.environment import Environment
 from sentry.snuba.dataset import Dataset
 from sentry.testutils.cases import PerformanceIssueTestCase, TestCase
@@ -577,20 +576,15 @@ class GroupEventFromEventTest(TestCase):
 @region_silo_test
 class GroupEventOccurrenceTest(TestCase, OccurrenceTestMixin):
     def test(self):
-        occurrence_data = self.build_occurrence_data(project_id=self.project.id)
-        occurrence, group_info = process_event_and_issue_occurrence(
-            occurrence_data,
-            event_data={
-                "event_id": occurrence_data["event_id"],
-                "project_id": occurrence_data["project_id"],
-                "level": "info",
-            },
+        occurrence, group_info = self.process_occurrence(
+            project_id=self.project.id,
+            event_data={"level": "info"},
         )
         assert group_info is not None
 
         event = Event(
-            occurrence_data["project_id"],
-            occurrence_data["event_id"],
+            occurrence.project_id,
+            occurrence.event_id,
             group_info.group.id,
             data={},
             snuba_data={"occurrence_id": occurrence.id},

+ 9 - 7
tests/sentry/eventstream/test_eventstream.py

@@ -13,7 +13,6 @@ from sentry.eventstore.models import Event
 from sentry.eventstream.base import EventStreamEventType
 from sentry.eventstream.kafka.backend import KafkaEventStream
 from sentry.eventstream.snuba import SnubaEventStream, SnubaProtocolEventStream
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.receivers import create_default_projects
 from sentry.snuba.dataset import Dataset, EntityKey
 from sentry.testutils.cases import SnubaTestCase, TestCase
@@ -374,15 +373,18 @@ class SnubaEventStreamTest(TestCase, SnubaTestCase, OccurrenceTestMixin):
 
         profile_message = load_data("generic-event-profiling")
         geo_interface = {"city": "San Francisco", "country_code": "US", "region": "California"}
-        event_data = profile_message["event"]
-        event_data["user"] = {"geo": geo_interface}
+        event_data = {
+            **profile_message["event"],
+            "user": {"geo": geo_interface},
+            "timestamp": datetime.utcnow().isoformat(),
+        }
 
         project_id = event_data.get("project_id", self.project.id)
-        event_data["timestamp"] = datetime.utcnow().isoformat()
 
-        occurrence, group_info = process_event_and_issue_occurrence(
-            self.build_occurrence_data(event_id=event_data["event_id"], project_id=project_id),
-            event_data,
+        occurrence, group_info = self.process_occurrence(
+            event_id=event_data["event_id"],
+            project_id=project_id,
+            event_data=event_data,
         )
         assert group_info is not None
 

+ 18 - 0
tests/sentry/issues/test_utils.py

@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import uuid
 from datetime import datetime, timedelta
 from typing import Any, Dict, List, Optional, Sequence, Tuple
@@ -10,6 +12,7 @@ from sentry.issues.escalating import GroupsCountResponse
 from sentry.issues.grouptype import ProfileFileIOGroupType
 from sentry.issues.ingest import process_occurrence_data, save_issue_occurrence
 from sentry.issues.issue_occurrence import IssueEvidence, IssueOccurrence, IssueOccurrenceData
+from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.group import Group
 from sentry.snuba.dataset import Dataset
 from sentry.testutils.helpers.datetime import iso_format
@@ -62,6 +65,21 @@ class OccurrenceTestMixin:
 
         return IssueOccurrence.from_dict(self.build_occurrence_data(**overrides))
 
+    def process_occurrence(
+        self, event_data: dict[str, Any] | None = None, **overrides
+    ) -> Tuple[IssueOccurrence, Optional[GroupInfo]]:
+        """
+        Testutil to build and process occurrence data instead of going through Kafka.
+        This ensures the occurrence data is well-formed.
+        """
+        occurrence_data = self.build_occurrence_data(**overrides)
+        if event_data:
+            if "event_id" not in event_data:
+                event_data["event_id"] = occurrence_data["event_id"]
+            if "project_id" not in event_data:
+                event_data["project_id"] = occurrence_data["project_id"]
+        return process_event_and_issue_occurrence(occurrence_data, event_data)
+
 
 class SearchIssueTestMixin(OccurrenceTestMixin):
     def store_search_issue(

+ 5 - 8
tests/sentry/models/test_group.py

@@ -9,7 +9,6 @@ from django.db.models import ProtectedError
 from django.utils import timezone
 
 from sentry.issues.grouptype import FeedbackGroup, ProfileFileIOGroupType
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.group import Group, GroupStatus, get_group_with_redirect
 from sentry.models.groupredirect import GroupRedirect
 from sentry.models.grouprelease import GroupRelease
@@ -416,16 +415,14 @@ class GroupGetLatestEventTest(TestCase, OccurrenceTestMixin):
 
     def test_get_latest_event_occurrence(self):
         event_id = uuid.uuid4().hex
-        occurrence_data = self.build_occurrence_data(event_id=event_id, project_id=self.project.id)
-        occurrence = process_event_and_issue_occurrence(
-            occurrence_data,
-            {
-                "event_id": event_id,
+        occurrence, _ = self.process_occurrence(
+            project_id=self.project.id,
+            event_id=event_id,
+            event_data={
                 "fingerprint": ["group-1"],
-                "project_id": self.project.id,
                 "timestamp": before_now(minutes=1).isoformat(),
             },
-        )[0]
+        )
 
         group = Group.objects.first()
         group.update(type=ProfileFileIOGroupType.type_id)

+ 4 - 9
tests/sentry/notifications/notifications/test_digests.py

@@ -11,7 +11,6 @@ import sentry
 from sentry.digests.backends.base import Backend
 from sentry.digests.backends.redis import RedisBackend
 from sentry.digests.notifications import event_to_record
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.projectownership import ProjectOwnership
 from sentry.models.rule import Rule
 from sentry.tasks.digests import deliver_digest
@@ -34,14 +33,10 @@ class DigestNotificationTest(TestCase, OccurrenceTestMixin, PerformanceIssueTest
             event = self.create_performance_issue()
         elif event_type == "generic":
             event_id = uuid.uuid4().hex
-            occurrence_data = self.build_occurrence_data(
-                event_id=event_id, project_id=self.project.id
-            )
-            occurrence, group_info = process_event_and_issue_occurrence(
-                occurrence_data,
-                {
-                    "event_id": event_id,
-                    "project_id": self.project.id,
+            _, group_info = self.process_occurrence(
+                event_id=event_id,
+                project_id=self.project.id,
+                event_data={
                     "timestamp": before_now(minutes=1).isoformat(),
                 },
             )

+ 4 - 8
tests/snuba/api/endpoints/test_organization_event_details.py

@@ -3,7 +3,6 @@ from datetime import timedelta
 import pytest
 from django.urls import NoReverseMatch, reverse
 
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.group import Group
 from sentry.testutils.cases import APITestCase, SnubaTestCase
 from sentry.testutils.helpers.datetime import before_now, iso_format
@@ -268,12 +267,9 @@ class OrganizationEventDetailsEndpointTest(APITestCase, SnubaTestCase, Occurrenc
         assert response.status_code == 404, response.content
 
     def test_generic_event(self):
-        occurrence_data = self.build_occurrence_data(project_id=self.project.id)
-        occurrence, group_info = process_event_and_issue_occurrence(
-            occurrence_data,
+        occurrence, _ = self.process_occurrence(
+            project_id=self.project.id,
             event_data={
-                "event_id": occurrence_data["event_id"],
-                "project_id": occurrence_data["project_id"],
                 "level": "info",
             },
         )
@@ -283,7 +279,7 @@ class OrganizationEventDetailsEndpointTest(APITestCase, SnubaTestCase, Occurrenc
             kwargs={
                 "organization_slug": self.project.organization.slug,
                 "project_slug": self.project.slug,
-                "event_id": occurrence_data["event_id"],
+                "event_id": occurrence.event_id,
             },
         )
 
@@ -291,7 +287,7 @@ class OrganizationEventDetailsEndpointTest(APITestCase, SnubaTestCase, Occurrenc
             response = self.client.get(url, format="json")
 
         assert response.status_code == 200, response.content
-        assert response.data["id"] == occurrence_data["event_id"]
+        assert response.data["id"] == occurrence.event_id
         assert response.data["projectSlug"] == self.project.slug
         assert response.data["occurrence"] is not None
         assert response.data["occurrence"]["id"] == occurrence.id

+ 10 - 17
tests/snuba/api/endpoints/test_organization_group_index_stats.py

@@ -1,7 +1,6 @@
 import uuid
 
 from sentry.issues.grouptype import ProfileFileIOGroupType
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.testutils.cases import APITestCase, SnubaTestCase
 from sentry.testutils.helpers import parse_link_header, with_feature
 from sentry.testutils.helpers.datetime import before_now, iso_format
@@ -100,15 +99,12 @@ class GroupListTest(APITestCase, SnubaTestCase, OccurrenceTestMixin):
 
     def test_issue_platform_issue(self):
         event_id = uuid.uuid4().hex
-        occurrence_data = self.build_occurrence_data(
-            event_id=event_id, project_id=self.project.id, type=ProfileFileIOGroupType.type_id
-        )
-        occurrence, group_info = process_event_and_issue_occurrence(
-            occurrence_data,
-            {
-                "event_id": event_id,
+        _, group_info = self.process_occurrence(
+            event_id=event_id,
+            project_id=self.project.id,
+            type=ProfileFileIOGroupType.type_id,
+            event_data={
                 "fingerprint": ["group-1"],
-                "project_id": self.project.id,
                 "timestamp": before_now(minutes=1).isoformat(),
             },
         )
@@ -137,15 +133,12 @@ class GroupListTest(APITestCase, SnubaTestCase, OccurrenceTestMixin):
 
     def test_issue_platform_mixed_issue_not_title(self):
         event_id = uuid.uuid4().hex
-        occurrence_data = self.build_occurrence_data(
-            event_id=event_id, project_id=self.project.id, type=ProfileFileIOGroupType.type_id
-        )
-        occurrence, group_info = process_event_and_issue_occurrence(
-            occurrence_data,
-            {
-                "event_id": event_id,
+        _, group_info = self.process_occurrence(
+            event_id=event_id,
+            project_id=self.project.id,
+            type=ProfileFileIOGroupType.type_id,
+            event_data={
                 "fingerprint": ["group-a"],
-                "project_id": self.project.id,
                 "timestamp": before_now(minutes=1).isoformat(),
             },
         )

+ 21 - 30
tests/snuba/api/endpoints/test_project_event_details.py

@@ -1,6 +1,5 @@
 from django.urls import reverse
 
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.testutils.cases import APITestCase, PerformanceIssueTestCase, SnubaTestCase
 from sentry.testutils.helpers.datetime import before_now, iso_format
 from sentry.testutils.silo import region_silo_test
@@ -130,26 +129,22 @@ class ProjectEventDetailsGenericTest(OccurrenceTestMixin, ProjectEventDetailsTes
         four_min_ago = iso_format(before_now(minutes=4))
 
         prev_event_id = "a" * 32
-        self.prev_event, prev_group_info = process_event_and_issue_occurrence(
-            self.build_occurrence_data(
-                event_id=prev_event_id, project_id=self.project.id, fingerprint=["group-1"]
-            ),
-            {
-                "event_id": prev_event_id,
-                "project_id": self.project.id,
+        self.prev_event, _ = self.process_occurrence(
+            event_id=prev_event_id,
+            project_id=self.project.id,
+            fingerprint=["group-1"],
+            event_data={
                 "timestamp": four_min_ago,
                 "message_timestamp": four_min_ago,
             },
         )
 
         cur_event_id = "b" * 32
-        self.cur_event, cur_group_info = process_event_and_issue_occurrence(
-            self.build_occurrence_data(
-                event_id=cur_event_id, project_id=self.project.id, fingerprint=["group-1"]
-            ),
-            {
-                "event_id": cur_event_id,
-                "project_id": self.project.id,
+        self.cur_event, cur_group_info = self.process_occurrence(
+            event_id=cur_event_id,
+            project_id=self.project.id,
+            fingerprint=["group-1"],
+            event_data={
                 "timestamp": three_min_ago,
                 "message_timestamp": three_min_ago,
             },
@@ -158,13 +153,11 @@ class ProjectEventDetailsGenericTest(OccurrenceTestMixin, ProjectEventDetailsTes
         self.cur_group = cur_group_info.group
 
         next_event_id = "c" * 32
-        self.next_event, next_group_info = process_event_and_issue_occurrence(
-            self.build_occurrence_data(
-                event_id=next_event_id, project_id=self.project.id, fingerprint=["group-1"]
-            ),
-            {
-                "event_id": next_event_id,
-                "project_id": self.project.id,
+        self.next_event, _ = self.process_occurrence(
+            event_id=next_event_id,
+            project_id=self.project.id,
+            fingerprint=["group-1"],
+            event_data={
                 "timestamp": two_min_ago,
                 "message_timestamp": two_min_ago,
                 "tags": {"environment": "production"},
@@ -172,18 +165,16 @@ class ProjectEventDetailsGenericTest(OccurrenceTestMixin, ProjectEventDetailsTes
         )
 
         unrelated_event_id = "d" * 32
-        process_event_and_issue_occurrence(
-            self.build_occurrence_data(
-                event_id=unrelated_event_id, project_id=self.project.id, fingerprint=["group-2"]
-            ),
-            {
-                "event_id": unrelated_event_id,
-                "project_id": self.project.id,
+        self.process_occurrence(
+            event_id=unrelated_event_id,
+            project_id=self.project.id,
+            fingerprint=["group-2"],
+            event_data={
                 "timestamp": one_min_ago,
                 "message_timestamp": one_min_ago,
                 "tags": {"environment": "production"},
             },
-        )[0]
+        )
 
     def test_generic_event_with_occurrence(self):
         url = reverse(

+ 10 - 13
tests/snuba/models/test_group.py

@@ -2,7 +2,6 @@ import uuid
 from unittest.mock import patch
 
 from sentry.issues.grouptype import PerformanceNPlusOneGroupType, ProfileFileIOGroupType
-from sentry.issues.occurrence_consumer import process_event_and_issue_occurrence
 from sentry.models.group import Group
 from sentry.testutils.cases import PerformanceIssueTestCase, SnubaTestCase, TestCase
 from sentry.testutils.helpers.datetime import before_now, iso_format
@@ -183,12 +182,11 @@ class GroupTestSnuba(TestCase, SnubaTestCase, PerformanceIssueTestCase, Occurren
 
     def test_profile_issue_helpful(self):
         event_id_1 = uuid.uuid4().hex
-        occurrence = process_event_and_issue_occurrence(
-            self.build_occurrence_data(event_id=event_id_1, project_id=self.project.id),
-            {
-                "event_id": event_id_1,
+        occurrence, _ = self.process_occurrence(
+            event_id=event_id_1,
+            project_id=self.project.id,
+            event_data={
                 "fingerprint": ["group-1"],
-                "project_id": self.project.id,
                 "timestamp": before_now(minutes=2).isoformat(),
                 "contexts": {
                     "profile": {"profile_id": uuid.uuid4().hex},
@@ -201,18 +199,17 @@ class GroupTestSnuba(TestCase, SnubaTestCase, PerformanceIssueTestCase, Occurren
                 },
                 "errors": [],
             },
-        )[0]
+        )
 
         event_id_2 = uuid.uuid4().hex
-        occurrence_2 = process_event_and_issue_occurrence(
-            self.build_occurrence_data(event_id=event_id_2, project_id=self.project.id),
-            {
-                "event_id": event_id_2,
+        occurrence_2, _ = self.process_occurrence(
+            event_id=event_id_2,
+            project_id=self.project.id,
+            event_data={
                 "fingerprint": ["group-1"],
-                "project_id": self.project.id,
                 "timestamp": before_now(minutes=1).isoformat(),
             },
-        )[0]
+        )
 
         group = Group.objects.first()
         group.update(type=ProfileFileIOGroupType.type_id)

Some files were not shown because too many files changed in this diff