|
@@ -1,12 +1,15 @@
|
|
from unittest import mock
|
|
from unittest import mock
|
|
|
|
|
|
|
|
+import pytest
|
|
from django.urls import reverse
|
|
from django.urls import reverse
|
|
from pytz import utc
|
|
from pytz import utc
|
|
from rest_framework.exceptions import ParseError
|
|
from rest_framework.exceptions import ParseError
|
|
|
|
|
|
-from sentry.testutils import APITestCase, SnubaTestCase
|
|
|
|
|
|
+from sentry.testutils import APITestCase, MetricsEnhancedPerformanceTestCase, SnubaTestCase
|
|
from sentry.testutils.helpers.datetime import before_now, iso_format
|
|
from sentry.testutils.helpers.datetime import before_now, iso_format
|
|
|
|
|
|
|
|
+pytestmark = pytest.mark.sentry_metrics
|
|
|
|
+
|
|
|
|
|
|
class OrganizationEventsMetaEndpoint(APITestCase, SnubaTestCase):
|
|
class OrganizationEventsMetaEndpoint(APITestCase, SnubaTestCase):
|
|
def setUp(self):
|
|
def setUp(self):
|
|
@@ -355,3 +358,130 @@ class OrganizationEventsRelatedIssuesEndpoint(APITestCase, SnubaTestCase):
|
|
assert len(response.data) == 1
|
|
assert len(response.data) == 1
|
|
assert response.data[0]["shortId"] == event.group.qualified_short_id
|
|
assert response.data[0]["shortId"] == event.group.qualified_short_id
|
|
assert int(response.data[0]["id"]) == event.group_id
|
|
assert int(response.data[0]["id"]) == event.group_id
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class OrganizationEventsMetricsCompatiblity(MetricsEnhancedPerformanceTestCase):
|
|
|
|
+ def setUp(self):
|
|
|
|
+ super().setUp()
|
|
|
|
+ self.min_ago = before_now(minutes=1)
|
|
|
|
+ self.two_min_ago = before_now(minutes=2)
|
|
|
|
+ self.features = {
|
|
|
|
+ "organizations:performance-use-metrics": True,
|
|
|
|
+ }
|
|
|
|
+ self.login_as(user=self.user)
|
|
|
|
+ self.project.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
|
|
|
|
+ # Don't create any txn on this, don't set its DS rules, it shouldn't show up anywhere
|
|
|
|
+ self.create_project()
|
|
|
|
+
|
|
|
|
+ def test_unparameterized_transactions(self):
|
|
|
|
+ # Make current project incompatible
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1, tags={"transaction": "<< unparameterized >>"}, timestamp=self.min_ago
|
|
|
|
+ )
|
|
|
|
+ url = reverse(
|
|
|
|
+ "sentry-api-0-organization-events-metrics-compatibility",
|
|
|
|
+ kwargs={"organization_slug": self.project.organization.slug},
|
|
|
|
+ )
|
|
|
|
+ response = self.client.get(url, format="json")
|
|
|
|
+
|
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
+ assert response.data["compatible_projects"] == []
|
|
|
|
+ assert response.data["dynamic_sampling_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["sum"]["metrics"] == 1
|
|
|
|
+ assert response.data["sum"]["metrics_unparam"] == 1
|
|
|
|
+ assert response.data["sum"]["metrics_null"] == 0
|
|
|
|
+
|
|
|
|
+ def test_null_transaction(self):
|
|
|
|
+ # Make current project incompatible
|
|
|
|
+ self.store_transaction_metric(1, tags={}, timestamp=self.min_ago)
|
|
|
|
+ url = reverse(
|
|
|
|
+ "sentry-api-0-organization-events-metrics-compatibility",
|
|
|
|
+ kwargs={"organization_slug": self.project.organization.slug},
|
|
|
|
+ )
|
|
|
|
+ response = self.client.get(url, format="json")
|
|
|
|
+
|
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
+ assert response.data["compatible_projects"] == []
|
|
|
|
+ assert response.data["dynamic_sampling_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["sum"]["metrics"] == 1
|
|
|
|
+ assert response.data["sum"]["metrics_unparam"] == 0
|
|
|
|
+ assert response.data["sum"]["metrics_null"] == 1
|
|
|
|
+
|
|
|
|
+ def test_no_transaction(self):
|
|
|
|
+ # Make current project incompatible by having nothing
|
|
|
|
+ url = reverse(
|
|
|
|
+ "sentry-api-0-organization-events-metrics-compatibility",
|
|
|
|
+ kwargs={"organization_slug": self.project.organization.slug},
|
|
|
|
+ )
|
|
|
|
+ response = self.client.get(url, format="json")
|
|
|
|
+
|
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
+ assert response.data["compatible_projects"] == []
|
|
|
|
+ assert response.data["dynamic_sampling_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["sum"]["metrics"] == 0
|
|
|
|
+ assert response.data["sum"]["metrics_unparam"] == 0
|
|
|
|
+ assert response.data["sum"]["metrics_null"] == 0
|
|
|
|
+
|
|
|
|
+ def test_has_transaction(self):
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
|
|
|
|
+ )
|
|
|
|
+ url = reverse(
|
|
|
|
+ "sentry-api-0-organization-events-metrics-compatibility",
|
|
|
|
+ kwargs={"organization_slug": self.project.organization.slug},
|
|
|
|
+ )
|
|
|
|
+ response = self.client.get(url, format="json")
|
|
|
|
+
|
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
+ assert response.data["compatible_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["dynamic_sampling_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["sum"]["metrics"] == 1
|
|
|
|
+ assert response.data["sum"]["metrics_unparam"] == 0
|
|
|
|
+ assert response.data["sum"]["metrics_null"] == 0
|
|
|
|
+
|
|
|
|
+ def test_multiple_projects(self):
|
|
|
|
+ project2 = self.create_project()
|
|
|
|
+ project2.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
|
|
|
|
+ project3 = self.create_project()
|
|
|
|
+ project3.update_option("sentry:dynamic_sampling", "something-it-doesn't-matter")
|
|
|
|
+ # Not setting DS, it shouldn't show up
|
|
|
|
+ project4 = self.create_project()
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago
|
|
|
|
+ )
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1, tags={"transaction": "foo_transaction"}, timestamp=self.min_ago, project=project4.id
|
|
|
|
+ )
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1,
|
|
|
|
+ tags={"transaction": "<< unparameterized >>"},
|
|
|
|
+ timestamp=self.min_ago,
|
|
|
|
+ project=project2.id,
|
|
|
|
+ )
|
|
|
|
+ self.store_transaction_metric(
|
|
|
|
+ 1,
|
|
|
|
+ tags={},
|
|
|
|
+ timestamp=self.min_ago,
|
|
|
|
+ project=project3.id,
|
|
|
|
+ )
|
|
|
|
+ self.store_event(
|
|
|
|
+ data={"timestamp": iso_format(self.min_ago), "transaction": "foo_transaction"},
|
|
|
|
+ project_id=self.project.id,
|
|
|
|
+ )
|
|
|
|
+ url = reverse(
|
|
|
|
+ "sentry-api-0-organization-events-metrics-compatibility",
|
|
|
|
+ kwargs={"organization_slug": self.project.organization.slug},
|
|
|
|
+ )
|
|
|
|
+ response = self.client.get(url, format="json")
|
|
|
|
+
|
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
+ assert response.data["compatible_projects"] == [self.project.id]
|
|
|
|
+ assert response.data["dynamic_sampling_projects"] == [
|
|
|
|
+ self.project.id,
|
|
|
|
+ project2.id,
|
|
|
|
+ project3.id,
|
|
|
|
+ ]
|
|
|
|
+ # project 4 shouldn't show up in these sums
|
|
|
|
+ assert response.data["sum"]["metrics"] == 3
|
|
|
|
+ assert response.data["sum"]["metrics_unparam"] == 1
|
|
|
|
+ assert response.data["sum"]["metrics_null"] == 1
|