Browse Source

feat(eventuser): Rm all references to EventUser model (#60753)

## Objective:

This PR removes all the code that makes queries to the EventUser model.
At this point, there are no queries made to this table, because we have
GA'd the feature flag and are generating the EventUser from Snuba/Event
object.
NisanthanNanthakumar 1 year ago
parent
commit
477321ac6d

+ 18 - 34
src/sentry/api/endpoints/project_users.py

@@ -1,13 +1,13 @@
 from rest_framework.request import Request
 from rest_framework.response import Response
 
-from sentry import analytics, features
+from sentry import analytics
 from sentry.api.api_publish_status import ApiPublishStatus
 from sentry.api.base import region_silo_endpoint
 from sentry.api.bases.project import ProjectEndpoint
-from sentry.api.paginator import CallbackPaginator, DateTimePaginator
+from sentry.api.paginator import CallbackPaginator
 from sentry.api.serializers import serialize
-from sentry.models.eventuser import EventUser as EventUser_model
+from sentry.api.serializers.models.eventuser import EventUserSerializer
 from sentry.types.ratelimit import RateLimit, RateLimitCategory
 from sentry.utils.eventuser import EventUser
 
@@ -51,37 +51,21 @@ class ProjectUsersEndpoint(ProjectEndpoint):
             except (ValueError, KeyError):
                 return Response([])
 
-        if not features.has("organizations:eventuser-from-snuba", project.organization):
-            queryset = EventUser_model.objects.filter(project_id=project.id)
-            if field and identifier:
-                queryset = queryset.filter(
-                    project_id=project.id,
-                    **{EventUser_model.attr_from_keyword(field): identifier},
-                )
+        keyword_filters = {}
+        if field and identifier:
+            keyword_filters[field] = [identifier]
 
-            return self.paginate(
-                request=request,
-                queryset=queryset,
-                order_by="-date_added",
-                paginator_cls=DateTimePaginator,
-                on_results=lambda x: serialize(x, request.user),
+        def callback(limit, offset):
+            return EventUser.for_projects(
+                projects=[project],
+                keyword_filters=keyword_filters,
+                result_limit=limit,
+                result_offset=offset,
             )
-        else:
-            keyword_filters = {}
-            if field and identifier:
-                keyword_filters[field] = [identifier]
 
-            def callback(limit, offset):
-                return EventUser.for_projects(
-                    projects=[project],
-                    keyword_filters=keyword_filters,
-                    result_limit=limit,
-                    result_offset=offset,
-                )
-
-            return self.paginate(
-                request=request,
-                paginator_cls=CallbackPaginator,
-                callback=callback,
-                on_results=lambda x: serialize(x, request.user),
-            )
+        return self.paginate(
+            request=request,
+            paginator_cls=CallbackPaginator,
+            callback=callback,
+            on_results=lambda x: serialize(x, request.user, EventUserSerializer()),
+        )

+ 0 - 1
src/sentry/api/serializers/models/__init__.py

@@ -22,7 +22,6 @@ from .doc_integration_avatar import *  # noqa: F401,F403
 from .environment import *  # noqa: F401,F403
 from .event import *  # noqa: F401,F403
 from .eventattachment import *  # noqa: F401,F403
-from .eventuser import *  # noqa: F401,F403
 from .exporteddata import *  # noqa: F401,F403
 from .external_actor import *  # noqa: F401,F403
 from .filechange import *  # noqa: F401,F403

+ 0 - 18
src/sentry/api/serializers/models/eventuser.py

@@ -1,26 +1,8 @@
 from sentry.api.serializers import Serializer, register
-from sentry.models.eventuser import EventUser as EventUser_model
 from sentry.utils.avatar import get_gravatar_url
 from sentry.utils.eventuser import EventUser
 
 
-@register(EventUser_model)
-class EventUserModelSerializer(Serializer):
-    def serialize(self, obj, attrs, user):
-        return {
-            "id": str(obj.id),
-            "hash": obj.hash,
-            "tagValue": obj.tag_value,
-            "identifier": obj.ident,
-            "username": obj.username,
-            "email": obj.email,
-            "name": obj.get_display_name(),
-            "ipAddress": obj.ip_address,
-            "dateCreated": obj.date_added,
-            "avatarUrl": get_gravatar_url(obj.email, size=32),
-        }
-
-
 @register(EventUser)
 class EventUserSerializer(Serializer):
     def serialize(self, obj, attrs, user):

+ 2 - 16
src/sentry/api/serializers/models/tagvalue.py

@@ -1,7 +1,4 @@
-from sentry import features
-from sentry.api.serializers import Serializer, serialize
-from sentry.models.eventuser import EventUser as EventUser_model
-from sentry.models.project import Project
+from sentry.api.serializers import Serializer
 from sentry.search.utils import convert_user_tag_to_query
 from sentry.utils.eventuser import EventUser
 
@@ -16,16 +13,7 @@ class UserTagValueSerializer(Serializer):
         self.project_id = project_id
 
     def get_attrs(self, item_list, user):
-        projects = Project.objects.filter(id=self.project_id)
-        if features.has("organizations:eventuser-from-snuba", projects[0].organization):
-            users = EventUser.for_tags(
-                project_id=self.project_id, values=[t.value for t in item_list]
-            )
-        else:
-            users = EventUser_model.for_tags(
-                project_id=self.project_id, values=[t.value for t in item_list]
-            )
-
+        users = EventUser.for_tags(project_id=self.project_id, values=[t.value for t in item_list])
         result = {}
         for item in item_list:
             result[item] = {"user": users.get(item.value)}
@@ -34,8 +22,6 @@ class UserTagValueSerializer(Serializer):
     def serialize(self, obj, attrs, user):
         if isinstance(attrs["user"], EventUser):
             result = attrs["user"].serialize()
-        elif isinstance(attrs["user"], EventUser_model):
-            result = serialize(attrs["user"], user)
         else:
             result = {"id": None}
 

+ 1 - 8
src/sentry/data_export/processors/issues_by_tag.py

@@ -1,7 +1,6 @@
 from __future__ import annotations
 
 from sentry import tagstore
-from sentry.models.eventuser import EventUser as EventUser_model
 from sentry.models.group import Group, get_group_with_redirect
 from sentry.models.project import Project
 from sentry.utils.eventuser import EventUser
@@ -98,13 +97,7 @@ class IssuesByTagProcessor:
         }
         if key == "user":
             euser = item._eventuser
-            result["id"] = (
-                euser.user_ident
-                if euser and isinstance(euser, EventUser)
-                else euser.ident
-                if euser and isinstance(euser, EventUser_model)
-                else ""
-            )
+            result["id"] = euser.user_ident if euser and isinstance(euser, EventUser) else ""
             result["email"] = euser.email if euser else ""
             result["username"] = euser.username if euser else ""
             result["ip_address"] = euser.ip_address if euser else ""

+ 4 - 45
src/sentry/ingest/userreport.py

@@ -6,10 +6,9 @@ from datetime import timedelta
 from django.db import IntegrityError, router
 from django.utils import timezone
 
-from sentry import analytics, eventstore, features
+from sentry import eventstore, features
 from sentry.eventstore.models import Event
 from sentry.feedback.usecases.create_feedback import shim_to_feedback
-from sentry.models.eventuser import EventUser as EventUser_model
 from sentry.models.userreport import UserReport
 from sentry.signals import user_feedback_received
 from sentry.utils import metrics
@@ -39,25 +38,11 @@ def save_userreport(
 
         event = eventstore.backend.get_event_by_id(project.id, report["event_id"])
 
-        euser, eventuser_record = find_event_user(event, report)
+        euser = find_event_user(event)
 
         if euser and not euser.name and report.get("name"):
             euser.name = report["name"]
 
-        # TODO(nisanthan): Continue updating the EventUser record's name
-        # And record metrics to see how often this logic hits.
-        if eventuser_record and not eventuser_record.name and report.get("name"):
-            eventuser_record.update(name=report["name"])
-            analytics.record(
-                "eventuser_endpoint.request",
-                project_id=project.id,
-                endpoint="sentry.ingest.userreport.eventuser_record_name.update",
-            )
-
-        if euser:
-            # TODO(nisanthan): Remove this eventually once UserReport model drops the event_user_id column
-            report["event_user_id"] = euser.id
-
         if event:
             # if the event is more than 30 minutes old, we don't allow updates
             # as it might be abusive
@@ -109,34 +94,8 @@ def save_userreport(
         return report_instance
 
 
-def find_eventuser_record(report_data, event):
+def find_event_user(event: Event):
     if not event:
-        if not report_data.get("email"):
-            return None
-        try:
-            return EventUser_model.objects.filter(
-                project_id=report_data["project_id"], email=report_data["email"]
-            )[0]
-        except IndexError:
-            return None
-
-    tag = event.get_tag("sentry:user")
-
-    if not tag:
         return None
-
-    try:
-        return EventUser_model.for_tags(project_id=report_data["project_id"], values=[tag])[tag]
-    except KeyError:
-        pass
-
-
-def find_event_user(event: Event, report_data):
-    if not event:
-        return None, None
-    eventuser_record = find_eventuser_record(report_data, event)
     eventuser = EventUser.from_event(event)
-    if eventuser_record:
-        eventuser.id = eventuser_record.id
-
-    return eventuser, eventuser_record
+    return eventuser

+ 2 - 11
src/sentry/search/utils.py

@@ -26,10 +26,7 @@ from sentry.services.hybrid_cloud.user.serial import serialize_rpc_user
 if TYPE_CHECKING:
     from sentry.api.event_search import SearchFilter
 
-from sentry import features
 from sentry.models.environment import Environment
-from sentry.models.eventuser import KEYWORD_MAP
-from sentry.models.eventuser import EventUser as EventUser_model
 from sentry.models.group import STATUS_QUERY_CHOICES
 from sentry.models.organizationmember import OrganizationMember
 from sentry.models.organizationmemberteam import OrganizationMemberTeam
@@ -40,7 +37,7 @@ from sentry.models.user import User
 from sentry.search.base import ANY
 from sentry.services.hybrid_cloud.user.service import user_service
 from sentry.types.group import SUBSTATUS_UPDATE_CHOICES
-from sentry.utils.eventuser import EventUser
+from sentry.utils.eventuser import KEYWORD_MAP, EventUser
 
 
 class InvalidQuery(Exception):
@@ -50,13 +47,7 @@ class InvalidQuery(Exception):
 def get_user_tag(projects: Sequence[Project], key: str, value: str) -> str:
     # TODO(dcramer): do something with case of multiple matches
     try:
-        if features.has("organizations:eventuser-from-snuba", projects[0].organization):
-            euser = EventUser.for_projects(projects, {key: [value]}, result_limit=1)[0]
-        else:
-            lookup = EventUser_model.attr_from_keyword(key)
-            euser = EventUser_model.objects.filter(
-                project_id__in=[p.id for p in projects], **{lookup: value}
-            )[0]
+        euser = EventUser.for_projects(projects, {key: [value]}, result_limit=1)[0]
     except (KeyError, IndexError):
         return f"{key}:{value}"
     except DataError:

+ 2 - 6
src/sentry/utils/eventuser.py

@@ -21,9 +21,8 @@ from snuba_sdk import (
     Request,
 )
 
-from sentry import analytics, features
+from sentry import analytics
 from sentry.eventstore.models import Event
-from sentry.models.eventuser import EventUser as EventUser_model
 from sentry.models.project import Project
 from sentry.snuba.dataset import Dataset, EntityKey
 from sentry.utils.avatar import get_gravatar_url
@@ -69,7 +68,7 @@ class EventUser:
     username: Optional[str]
     name: Optional[str]
     ip_address: Optional[str]
-    user_ident: Optional[int]
+    user_ident: Optional[int | str]
     id: Optional[int] = None  # EventUser model id
 
     def __hash__(self):
@@ -288,9 +287,6 @@ class EventUser:
         """
         projects = Project.objects.filter(id=project_id)
 
-        if not features.has("organizations:eventuser-from-snuba", projects[0].organization):
-            return EventUser_model.for_tags(project_id, values)
-
         result = {}
         keyword_filters: Dict[str, Any] = {}
         for value in values:

+ 21 - 3
tests/snuba/tagstore/test_tagstore_backend.py

@@ -7,7 +7,6 @@ from django.utils import timezone
 
 from sentry.issues.grouptype import ProfileFileIOGroupType
 from sentry.models.environment import Environment
-from sentry.models.eventuser import EventUser
 from sentry.models.release import Release
 from sentry.models.releaseprojectenvironment import ReleaseProjectEnvironment, ReleaseStages
 from sentry.search.events.constants import (
@@ -27,6 +26,7 @@ from sentry.tagstore.types import GroupTagValue, TagValue
 from sentry.testutils.abstract import Abstract
 from sentry.testutils.cases import PerformanceIssueTestCase, SnubaTestCase, TestCase
 from sentry.testutils.helpers.datetime import before_now, iso_format
+from sentry.utils.eventuser import EventUser
 from sentry.utils.samples import load_data
 from tests.sentry.issues.test_utils import SearchIssueTestMixin
 
@@ -697,7 +697,16 @@ class TagStorageTest(TestCase, SnubaTestCase, SearchIssueTestMixin, PerformanceI
     @mock.patch("sentry.analytics.record")
     def test_get_group_tag_values_for_users(self, mock_record):
         result = self.ts.get_group_tag_values_for_users(
-            [EventUser(project_id=self.proj1.id, ident="user1")],
+            [
+                EventUser(
+                    project_id=self.proj1.id,
+                    email=None,
+                    username=None,
+                    name=None,
+                    ip_address=None,
+                    user_ident="user1",
+                )
+            ],
             tenant_ids={"referrer": "r", "organization_id": 1234},
         )
         assert len(result) == 2
@@ -713,7 +722,16 @@ class TagStorageTest(TestCase, SnubaTestCase, SearchIssueTestMixin, PerformanceI
             assert v.value == "user1"
 
         result = self.ts.get_group_tag_values_for_users(
-            [EventUser(project_id=self.proj1.id, ident="user2")],
+            [
+                EventUser(
+                    project_id=self.proj1.id,
+                    email=None,
+                    username=None,
+                    name=None,
+                    ip_address=None,
+                    user_ident="user2",
+                )
+            ],
             tenant_ids={"referrer": "r", "organization_id": 1234},
         )
         assert len(result) == 1