David Burke 4 лет назад
Родитель
Сommit
5a4aab8dde

+ 4 - 1
djstripe_ext/tests.py

@@ -71,8 +71,11 @@ class SubscriptionAPITestCase(APITestCase):
         with freeze_time(timezone.datetime(2020, 1, 5)):
             baker.make("events.Event")
             baker.make("events.Event", issue__project__organization=self.organization)
+            baker.make(
+                "performance.TransactionEvent", project__organization=self.organization
+            )
         res = self.client.get(url)
-        self.assertEqual(res.data, 1)
+        self.assertEqual(res.data, 2)
 
     def test_events_count_without_customer(self):
         """

+ 8 - 5
djstripe_ext/views.py

@@ -58,11 +58,14 @@ class SubscriptionViewSet(viewsets.ModelViewSet):
         if not subscription:
             return Response(0)
         organization = subscription.customer.subscriber
-        event_count = Event.objects.filter(
-            issue__project__organization=organization,
-            created__gte=subscription.current_period_start,
-            created__lt=subscription.current_period_end,
-        ).count()
+        event_count = (
+            Event.objects.for_organization(organization)
+            .filter(
+                created__gte=subscription.current_period_start,
+                created__lt=subscription.current_period_end,
+            )
+            .count()
+        )
         return Response(event_count)
 
 

+ 15 - 0
events/models.py

@@ -1,5 +1,6 @@
 import uuid
 from django.db import models
+from django.db.models import Q
 from user_reports.models import UserReport
 
 
@@ -18,6 +19,18 @@ class EventTag(models.Model):
         unique_together = ("key", "value")
 
 
+class EventManager(models.Manager):
+    def for_organization(self, organization):
+        return (
+            super()
+            .get_queryset()
+            .filter(
+                Q(issue__project__organization=organization)
+                | Q(transactionevent__project__organization=organization)
+            )
+        )
+
+
 class Event(models.Model):
     """
     An individual event. An issue is a set of like-events.
@@ -45,6 +58,8 @@ class Event(models.Model):
         "releases.Release", blank=True, null=True, on_delete=models.SET_NULL
     )
 
+    objects = EventManager()
+
     class Meta:
         ordering = ["-created"]
 

+ 0 - 32
events/serializers.py

@@ -404,35 +404,3 @@ class StoreCSPReportSerializer(BaseSerializer):
 class EnvelopeHeaderSerializer(serializers.Serializer):
     event_id = serializers.UUIDField()
     sent_at = FlexibleDateTimeField(required=False)
-
-
-class SpanSerializer(serializers.Serializer):
-    data = serializers.JSONField(required=False)
-    description = serializers.CharField(required=False)
-    op = serializers.CharField(required=False)
-    parent_span_id = serializers.CharField(required=False)
-    span_id = serializers.CharField(required=False)
-    start_timestamp = FlexibleDateTimeField()
-    status = serializers.CharField(required=False)
-    tags = serializers.JSONField(required=False)
-    timestamp = FlexibleDateTimeField()
-    trace_id = serializers.UUIDField()
-    same_process_as_parent = serializers.BooleanField(required=False)
-
-
-class TransactionSerializer(SentrySDKEventSerializer):
-    type = serializers.CharField()
-    contexts = serializers.JSONField()
-    measurements = serializers.JSONField(required=False)
-    spans = serializers.ListField(
-        child=SpanSerializer(), required=False, allow_empty=True
-    )
-    start_timestamp = FlexibleDateTimeField()
-    timestamp = FlexibleDateTimeField()
-    transaction = serializers.CharField()
-
-    def create(self, data):
-        return Event.objects.create(
-            event_id=data["event_id"], timestamp=data["timestamp"], data={}
-        )
-

+ 6 - 7
events/views.py

@@ -12,12 +12,12 @@ from rest_framework.response import Response
 from rest_framework.views import APIView
 from sentry.utils.auth import parse_auth_header
 from projects.models import Project
+from performance.serializers import TransactionEventSerializer
 from .serializers import (
     StoreDefaultSerializer,
     StoreErrorSerializer,
     StoreCSPReportSerializer,
     EnvelopeHeaderSerializer,
-    TransactionSerializer,
 )
 from .parsers import EnvelopeParser
 from .negotiation import IgnoreClientContentNegotiation
@@ -134,7 +134,7 @@ class EnvelopeAPIView(BaseEventAPIView):
     parser_classes = [EnvelopeParser]
 
     def get_serializer_class(self):
-        return TransactionSerializer
+        return TransactionEventSerializer
 
     def post(self, request, *args, **kwargs):
         if settings.EVENT_STORE_DEBUG:
@@ -147,12 +147,11 @@ class EnvelopeAPIView(BaseEventAPIView):
         event_header_serializer = EnvelopeHeaderSerializer(data=data.pop(0))
         event_header_serializer.is_valid(raise_exception=True)
         # Multi part envelopes are not yet supported
-        data.pop(0)  # Second header isn't used at this time
+        data.pop(0)  # Message header isn't used at this time
 
         serializer = self.get_serializer_class()(
             data=data.pop(0), context={"request": self.request, "project": project}
         )
-        if serializer.is_valid():
-            event = serializer.save()
-            return Response({"id": event.event_id_hex})
-        return Response()
+        serializer.is_valid(raise_exception=True)
+        event = serializer.save()
+        return Response({"id": event.event_id_hex})

+ 1 - 0
glitchtip/settings.py

@@ -149,6 +149,7 @@ INSTALLED_APPS = [
     "issues",
     "users",
     "user_reports",
+    "performance",
     "projects",
     "teams",
     "releases",

+ 8 - 0
organizations_ext/tasks.py

@@ -23,6 +23,14 @@ def set_organization_throttle():
                     )
                 ),
             )
+            + Count(
+                "projects__transactionevent",
+                filter=Q(
+                    projects__transactionevent__created__gte=F(
+                        "djstripe_customers__subscriptions__current_period_start"
+                    )
+                ),
+            )
         )
 
         orgs_over_quota = free_tier_organizations.filter(

+ 6 - 1
organizations_ext/tests/test_throttling.py

@@ -53,7 +53,12 @@ class OrganizationThrottlingTestCase(TestCase):
 
             # Throttle again
             baker.make(
-                "events.Event", issue__project__organization=organization, _quantity=11
+                "events.Event", issue__project__organization=organization, _quantity=10
+            )
+            baker.make(
+                "performance.TransactionEvent",
+                project__organization=organization,
+                _quantity=1,
             )
             set_organization_throttle()
             organization.refresh_from_db()

+ 4 - 0
organizations_ext/urls.py

@@ -4,6 +4,7 @@ from issues.views import IssueViewSet
 from teams.views import NestedTeamViewSet
 from environments.views import EnvironmentViewSet
 from releases.views import ReleaseViewSet
+from performance.views import TransactionViewSet
 from glitchtip.routers import BulkSimpleRouter
 from .views import (
     OrganizationViewSet,
@@ -38,6 +39,9 @@ organizations_router.register(
 organizations_router.register(
     r"releases", ReleaseViewSet, basename="organization-releases"
 )
+organizations_router.register(
+    r"transactions", TransactionViewSet, basename="organization-transactions"
+)
 
 urlpatterns = [
     path("", include(router.urls)),

+ 0 - 0
performance/__init__.py


Некоторые файлы не были показаны из-за большого количества измененных файлов