diff --git a/src/sentry/conf/server.py b/src/sentry/conf/server.py index fa6093e67c510..ec00270c9a535 100644 --- a/src/sentry/conf/server.py +++ b/src/sentry/conf/server.py @@ -1378,6 +1378,8 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str: "organizations:escalating-issues-msteams": False, # Enable archive/escalating issue workflow features in v2 "organizations:escalating-issues-v2": False, + # Enable emiting escalating data to the metrics backend + "organizations:escalating-metrics-backend": False, # Allows an org to have a larger set of project ownership rules per project "organizations:higher-ownership-limit": False, # Enable Monitors (Crons) view diff --git a/src/sentry/features/__init__.py b/src/sentry/features/__init__.py index c09064f23ab01..9a770174cbc30 100644 --- a/src/sentry/features/__init__.py +++ b/src/sentry/features/__init__.py @@ -232,6 +232,7 @@ default_manager.add("organizations:escalating-issues", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) default_manager.add("organizations:escalating-issues-msteams", OrganizationFeature, FeatureHandlerStrategy.REMOTE) default_manager.add("organizations:escalating-issues-v2", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) +default_manager.add("organizations:escalating-metrics-backend", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) default_manager.add("organizations:integrations-gh-invite", OrganizationFeature, FeatureHandlerStrategy.REMOTE) default_manager.add("organizations:event-attachments", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) default_manager.add("organizations:global-views", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) diff --git a/src/sentry/tasks/post_process.py b/src/sentry/tasks/post_process.py index 918936576f9ed..8660cc3e286c6 100644 --- a/src/sentry/tasks/post_process.py +++ b/src/sentry/tasks/post_process.py @@ -16,6 +16,8 @@ from sentry.issues.grouptype import GroupCategory from sentry.issues.issue_occurrence import IssueOccurrence from sentry.killswitches import killswitch_matches_context +from sentry.sentry_metrics.client import generic_metrics_backend +from sentry.sentry_metrics.use_case_id_registry import UseCaseID from sentry.signals import event_processed, issue_unignored, transaction_processed from sentry.silo import SiloMode from sentry.tasks.base import instrumented_task @@ -116,6 +118,21 @@ def _capture_event_stats(event: Event) -> None: metrics.timing("events.size.data", event.size, tags=tags) +def _update_escalating_metrics(event: Event) -> None: + """ + Update metrics for escalating issues when an event is processed. + """ + generic_metrics_backend.counter( + UseCaseID.ESCALATING_ISSUES, + org_id=event.project.organization_id, + project_id=event.project.id, + metric_name="event_ingested", + value=1, + tags={"group": str(event.group_id)}, + unit=None, + ) + + def _capture_group_stats(job: PostProcessJob) -> None: event = job["event"] if not job["group_state"]["is_new"] or not should_write_event_stats(event): @@ -573,6 +590,8 @@ def get_event_raise_exception() -> Event: update_event_groups(event, group_states) bind_organization_context(event.project.organization) _capture_event_stats(event) + if features.has("organizations:escalating-metrics-backend", event.project.organization): + _update_escalating_metrics(event) group_events: Mapping[int, GroupEvent] = { ge.group_id: ge for ge in list(event.build_group_events()) diff --git a/tests/relay_integration/lang/javascript/test_plugin.py b/tests/relay_integration/lang/javascript/test_plugin.py index 6f9a0a1fe1232..9a19ed3129637 100644 --- a/tests/relay_integration/lang/javascript/test_plugin.py +++ b/tests/relay_integration/lang/javascript/test_plugin.py @@ -8,6 +8,7 @@ import pytest import responses +from django.conf import settings from django.core.files.base import ContentFile from django.utils import timezone @@ -1308,6 +1309,9 @@ def test_no_fetch_from_http(self): body=load_fixture("node_app.min.js.map"), content_type="application/javascript; charset=utf-8", ) + responses.add_passthru( + settings.SENTRY_SNUBA + "/tests/entities/generic_metrics_counters/insert", + ) data = { "timestamp": self.min_ago, @@ -1383,6 +1387,10 @@ def test_html_file_with_query_param_ending_with_js_extension(self): "" ), ) + responses.add_passthru( + settings.SENTRY_SNUBA + "/tests/entities/generic_metrics_counters/insert", + ) + data = { "timestamp": self.min_ago, "message": "hello", diff --git a/tests/sentry/notifications/test_notifications.py b/tests/sentry/notifications/test_notifications.py index 33c3e5e8feb6b..574ec002f6137 100644 --- a/tests/sentry/notifications/test_notifications.py +++ b/tests/sentry/notifications/test_notifications.py @@ -5,6 +5,7 @@ from urllib.parse import parse_qs import responses +from django.conf import settings from django.core import mail from django.core.mail.message import EmailMultiAlternatives from django.utils import timezone @@ -106,6 +107,9 @@ def setUp(self): status=200, content_type="application/json", ) + responses.add_passthru( + settings.SENTRY_SNUBA + "/tests/entities/generic_metrics_counters/insert", + ) self.name = self.user.get_display_name() self.short_id = self.group.qualified_short_id diff --git a/tests/sentry/sentry_metrics/test_snuba.py b/tests/sentry/sentry_metrics/test_snuba.py index 34cd96d8ddc07..3f6212551cb0f 100644 --- a/tests/sentry/sentry_metrics/test_snuba.py +++ b/tests/sentry/sentry_metrics/test_snuba.py @@ -13,7 +13,6 @@ class MetricsInterfaceTestCase(BaseMetricsLayerTestCase, TestCase, GenericMetricsTestMixIn): def setUp(self): super().setUp() - self.test_project = self.create_project() class SnubaMetricsInterfaceTest(MetricsInterfaceTestCase): @@ -33,7 +32,7 @@ def test_count_query(self): generic_metrics_backend.distribution( self.use_case_id, self.organization.id, - self.test_project.id, + self.project.id, self.metric_name, [100, 200, 300], {}, @@ -49,7 +48,6 @@ def test_count_query(self): metric_mri=self.get_mri(self.metric_name, "d", self.use_case_id, self.unit), ), ], - project_ids=[self.test_project.id], groupby=[], orderby=[], limit=Limit(limit=1), @@ -58,7 +56,7 @@ def test_count_query(self): ) data = get_series( - [self.test_project], + [self.project], metrics_query=metrics_query, include_meta=True, use_case_id=self.use_case_id,