Browse Source

feat(eventstore): Add get_event_by_id (#14249)

Adds eventstore function to fetch a single event given a project ID
and event ID. This should eventually replace EventManager.from_event_id
and SnubaEvent.get_event functions.
Lyn Nagara 5 years ago
parent
commit
2553424e0a

+ 2 - 2
src/sentry/api/endpoints/project_user_reports.py

@@ -6,6 +6,7 @@ from django.utils import timezone
 from rest_framework import serializers
 from uuid import uuid4
 
+from sentry import eventstore
 from sentry.api.authentication import DSNAuthentication
 from sentry.api.base import DocSection, EnvironmentMixin
 from sentry.api.bases.project import ProjectEndpoint
@@ -19,7 +20,6 @@ from sentry.models import (
     EventUser,
     GroupStatus,
     ProjectKey,
-    SnubaEvent,
     UserReport)
 from sentry.signals import user_feedback_received
 from sentry.utils.apidocs import scenario, attach_scenarios
@@ -139,7 +139,7 @@ class ProjectUserReportsEndpoint(ProjectEndpoint, EnvironmentMixin):
         report['event_id'] = report['event_id'].lower()
         report['project'] = project
 
-        event = SnubaEvent.objects.from_event_id(report['event_id'], project.id)
+        event = eventstore.get_event_by_id(project.id, report['event_id'])
 
         # TODO(dcramer): we should probably create the user if they dont
         # exist, and ideally we'd also associate that with the event

+ 18 - 1
src/sentry/eventstore/snuba/backend.py

@@ -1,6 +1,6 @@
 from __future__ import absolute_import
 
-
+from sentry.models import SnubaEvent
 from sentry.eventstore.base import EventStorage
 
 
@@ -8,3 +8,20 @@ class SnubaEventStorage(EventStorage):
     """
     Eventstore backend backed by Snuba
     """
+
+    def get_event_by_id(self, project_id, event_id, additional_columns=None):
+        """
+        Get an event given a project ID and event ID
+        Returns None if an event cannot be found
+        """
+        cols = self.__get_columns(additional_columns)
+
+        return SnubaEvent.get_event(project_id, event_id, snuba_cols=cols)
+
+    def __get_columns(self, additional_columns):
+        columns = EventStorage.minimal_columns
+
+        if additional_columns:
+            columns = set(columns + additional_columns)
+
+        return [col.value for col in columns]

+ 69 - 0
tests/sentry/eventstore/snuba/test_backend.py

@@ -0,0 +1,69 @@
+from __future__ import absolute_import
+
+from datetime import timedelta
+from django.utils import timezone
+
+from sentry.testutils import TestCase
+from sentry.eventstore.snuba.backend import SnubaEventStorage
+
+
+class SnubaEventStorageTest(TestCase):
+    def setUp(self):
+        self.min_ago = (timezone.now() - timedelta(minutes=1)).isoformat()[:19]
+        self.two_min_ago = (timezone.now() - timedelta(minutes=2)).isoformat()[:19]
+        self.store_event(
+            data={
+                'event_id': 'a' * 32,
+                'type': 'default',
+                'platform': 'python',
+                'fingerprint': ['group1'],
+                'timestamp': self.two_min_ago,
+                'tags': {'foo': '1'},
+            },
+            project_id=self.project.id,
+        )
+        self.store_event(
+            data={
+                'event_id': 'b' * 32,
+                'type': 'default',
+                'platform': 'python',
+                'fingerprint': ['group1'],
+                'timestamp': self.min_ago,
+                'tags': {'foo': '1'},
+            },
+            project_id=self.project.id,
+        )
+        self.store_event(
+            data={
+                'event_id': 'c' * 32,
+                'type': 'default',
+                'platform': 'python',
+                'fingerprint': ['group2'],
+                'timestamp': self.min_ago,
+                'tags': {'foo': '1'},
+            },
+            project_id=self.project.id,
+        )
+
+        self.eventstore = SnubaEventStorage()
+
+    def test_get_event_by_id(self):
+        # Get event with default columns
+        event = self.eventstore.get_event_by_id(self.project.id, 'a' * 32)
+
+        assert event.id == 'a' * 32
+        assert event.event_id == 'a' * 32
+        assert event.project_id == self.project.id
+        assert len(event.snuba_data.keys()) == 4
+
+        # Get all columns
+        event = self.eventstore.get_event_by_id(
+            self.project.id, 'b' * 32, self.eventstore.full_columns)
+        assert event.id == 'b' * 32
+        assert event.event_id == 'b' * 32
+        assert event.project_id == self.project.id
+        assert len(event.snuba_data.keys()) == 16
+
+        # Get non existent event
+        event = self.eventstore.get_event_by_id(self.project.id, 'd' * 32)
+        assert event is None

+ 3 - 3
tests/sentry/eventstore/test_base.py

@@ -3,7 +3,7 @@ from __future__ import absolute_import
 from datetime import timedelta
 from django.utils import timezone
 
-from sentry.models import SnubaEvent
+from sentry import eventstore
 from sentry.testutils import TestCase
 from sentry.eventstore.base import EventStorage
 
@@ -44,8 +44,8 @@ class EventStorageTest(TestCase):
             project_id=self.project.id,
         )
 
-        event = SnubaEvent.objects.from_event_id('a' * 32, self.project.id)
-        event2 = SnubaEvent.objects.from_event_id('b' * 32, self.project.id)
+        event = eventstore.get_event_by_id(self.project.id, 'a' * 32)
+        event2 = eventstore.get_event_by_id(self.project.id, 'b' * 32)
         assert event.data._node_data is None
         self.eventstorage.bind_nodes([event, event2], 'data')
         assert event.data._node_data is not None