From 4374228de0e5b4d2068e0f502ff564ec6297c146 Mon Sep 17 00:00:00 2001 From: Colleen O'Rourke Date: Fri, 10 Jan 2025 10:30:42 -0800 Subject: [PATCH] chore(alerts): Remove more activated alerts code (#83212) Removes deprecated activated alerts code from the test utils and alert creation code as well as a few other lingering spots. --- src/sentry/features/temporary.py | 2 - .../endpoints/serializers/__init__.py | 1 - .../serializers/alert_rule_activations.py | 33 ------ src/sentry/incidents/logic.py | 33 +----- src/sentry/incidents/models/__init__.py | 1 + src/sentry/incidents/models/alert_rule.py | 54 --------- src/sentry/integrations/metric_alerts.py | 6 - src/sentry/testutils/factories.py | 34 +----- src/sentry/testutils/fixtures.py | 35 +----- src/sentry/testutils/helpers/backups.py | 26 ++--- .../test_organization_alert_rule_details.py | 36 ------ .../test_organization_alert_rule_index.py | 5 +- tests/sentry/incidents/test_logic.py | 110 +++++------------- .../incidents/test_subscription_processor.py | 2 - 14 files changed, 49 insertions(+), 329 deletions(-) delete mode 100644 src/sentry/incidents/endpoints/serializers/alert_rule_activations.py diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py index b44f5b8c03bc43..ec98fb80e83633 100644 --- a/src/sentry/features/temporary.py +++ b/src/sentry/features/temporary.py @@ -42,8 +42,6 @@ def register_temporary_features(manager: FeatureManager): # Organization scoped features that are in development or in customer trials. # ############################################################################### - # Enables activated alert rules - manager.add("organizations:activated-alert-rules", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Enable AI Issue Summary feature on the Issue Details page. manager.add("organizations:ai-summary", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Enables alert creation on indexed events in UI (use for PoC/testing only) diff --git a/src/sentry/incidents/endpoints/serializers/__init__.py b/src/sentry/incidents/endpoints/serializers/__init__.py index 0b7fea3eb50e08..c5b8be09dd2d7e 100644 --- a/src/sentry/incidents/endpoints/serializers/__init__.py +++ b/src/sentry/incidents/endpoints/serializers/__init__.py @@ -1,5 +1,4 @@ from .alert_rule import * # NOQA -from .alert_rule_activations import * # NOQA from .alert_rule_trigger import * # NOQA from .alert_rule_trigger_action import * # NOQA from .query_subscription import * # NOQA diff --git a/src/sentry/incidents/endpoints/serializers/alert_rule_activations.py b/src/sentry/incidents/endpoints/serializers/alert_rule_activations.py deleted file mode 100644 index a72158d01ca3cb..00000000000000 --- a/src/sentry/incidents/endpoints/serializers/alert_rule_activations.py +++ /dev/null @@ -1,33 +0,0 @@ -from datetime import datetime -from typing import TypedDict - -from sentry.api.serializers import Serializer, register -from sentry.incidents.models.alert_rule_activations import AlertRuleActivations - - -class AlertRuleActivationsResponse(TypedDict): - id: str - activator: str - alertRuleId: str - conditionType: str - dateCreated: datetime - finishedAt: datetime - isComplete: bool - metricValue: int - querySubscriptionId: str - - -@register(AlertRuleActivations) -class AlertRuleActivationsSerializer(Serializer): - def serialize(self, obj, attrs, user, **kwargs) -> AlertRuleActivationsResponse: - return { - "id": str(obj.id), - "activator": obj.activator, - "alertRuleId": str(obj.alert_rule_id), - "conditionType": str(obj.condition_type), - "dateCreated": obj.date_added, - "finishedAt": obj.finished_at, - "isComplete": obj.is_complete(), - "metricValue": obj.metric_value, - "querySubscriptionId": str(obj.query_subscription_id), - } diff --git a/src/sentry/incidents/logic.py b/src/sentry/incidents/logic.py index 3799eb14ada247..f9a87fd8864eef 100644 --- a/src/sentry/incidents/logic.py +++ b/src/sentry/incidents/logic.py @@ -7,7 +7,7 @@ from dataclasses import dataclass, replace from datetime import datetime, timedelta, timezone from enum import Enum, auto -from typing import TYPE_CHECKING, Any, TypedDict +from typing import Any, TypedDict from uuid import UUID, uuid4 from django.db import router, transaction @@ -29,7 +29,6 @@ AlertRuleActivity, AlertRuleActivityType, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleProjects, AlertRuleSeasonality, AlertRuleSensitivity, @@ -38,10 +37,6 @@ AlertRuleTrigger, AlertRuleTriggerAction, ) -from sentry.incidents.models.alert_rule_activations import ( - AlertRuleActivationCondition, - AlertRuleActivations, -) from sentry.incidents.models.incident import ( Incident, IncidentActivity, @@ -105,10 +100,6 @@ from sentry.utils.audit import create_audit_entry_from_user from sentry.utils.snuba import is_measurement -if TYPE_CHECKING: - from sentry.incidents.utils.types import AlertRuleActivationConditionType - - # We can return an incident as "windowed" which returns a range of points around the start of the incident # It attempts to center the start of the incident, only showing earlier data if there isn't enough time # after the incident started to display the correct start date. @@ -153,7 +144,6 @@ def create_incident( projects: Collection[Project] = (), user: RpcUser | None = None, alert_rule: AlertRule | None = None, - activation: AlertRuleActivations | None = None, subscription: QuerySubscription | None = None, ) -> Incident: if date_detected is None: @@ -169,7 +159,6 @@ def create_incident( date_started=date_started, date_detected=date_detected, alert_rule=alert_rule, - activation=activation, subscription=subscription, ) if projects: @@ -513,8 +502,6 @@ def create_alert_rule( user: RpcUser | None = None, event_types: Collection[SnubaQueryEventType.EventType] = (), comparison_delta: int | None = None, - monitor_type: AlertRuleMonitorTypeInt = AlertRuleMonitorTypeInt.CONTINUOUS, - activation_condition: AlertRuleActivationConditionType | None = None, description: str | None = None, sensitivity: AlertRuleSensitivity | None = None, seasonality: AlertRuleSeasonality | None = None, @@ -556,9 +543,6 @@ def create_alert_rule( if detection_type == AlertRuleDetectionType.DYNAMIC.value and not has_anomaly_detection: raise ResourceDoesNotExist("Your organization does not have access to this feature.") - if monitor_type == AlertRuleMonitorTypeInt.ACTIVATED and not activation_condition: - raise ValidationError("Activation condition required for activated alert rule") - if detection_type == AlertRuleDetectionType.DYNAMIC: resolution = time_window # NOTE: we hardcode seasonality for EA @@ -617,7 +601,6 @@ def create_alert_rule( resolve_threshold=resolve_threshold, threshold_period=threshold_period, comparison_delta=comparison_delta, - monitor_type=monitor_type, description=description, sensitivity=sensitivity, seasonality=seasonality, @@ -639,12 +622,6 @@ def create_alert_rule( event=audit_log.get_event_id("ALERT_RULE_ADD"), ) - if monitor_type == AlertRuleMonitorTypeInt.ACTIVATED and activation_condition: - # NOTE: if monitor_type is activated, activation_condition is required - AlertRuleActivationCondition.objects.create( - alert_rule=alert_rule, condition_type=activation_condition.value - ) - # initialize projects join table for alert rules arps = [AlertRuleProjects(alert_rule=alert_rule, project=project) for project in projects] AlertRuleProjects.objects.bulk_create(arps) @@ -745,7 +722,6 @@ def update_alert_rule( user: RpcUser | None = None, event_types: Collection[SnubaQueryEventType.EventType] | None = None, comparison_delta: int | None | NotSet = NOT_SET, - monitor_type: AlertRuleMonitorTypeInt | None = None, description: str | None = None, sensitivity: AlertRuleSensitivity | None | NotSet = NOT_SET, seasonality: AlertRuleSeasonality | None | NotSet = NOT_SET, @@ -807,9 +783,6 @@ def update_alert_rule( updated_query_fields["dataset"] = dataset if query_type is not None: updated_query_fields["query_type"] = query_type - if monitor_type is not None: - # TODO: determine how to convert activated alert into continuous alert and vice versa - pass if event_types is not None: updated_query_fields["event_types"] = event_types if owner is not NOT_SET: @@ -1080,10 +1053,6 @@ class AlertRuleTriggerLabelAlreadyUsedError(Exception): pass -class AlertRuleActivationConditionLabelAlreadyUsedError(Exception): - pass - - class ProjectsNotAssociatedWithAlertRuleError(Exception): def __init__(self, project_slugs: Collection[str]) -> None: self.project_slugs = project_slugs diff --git a/src/sentry/incidents/models/__init__.py b/src/sentry/incidents/models/__init__.py index e69de29bb2d1d6..232d49eed51719 100644 --- a/src/sentry/incidents/models/__init__.py +++ b/src/sentry/incidents/models/__init__.py @@ -0,0 +1 @@ +from .alert_rule_activations import * # NOQA diff --git a/src/sentry/incidents/models/alert_rule.py b/src/sentry/incidents/models/alert_rule.py index 491bc4b0b36256..22b624495d3135 100644 --- a/src/sentry/incidents/models/alert_rule.py +++ b/src/sentry/incidents/models/alert_rule.py @@ -26,10 +26,7 @@ from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey from sentry.db.models.manager.base import BaseManager from sentry.db.models.manager.base_query_set import BaseQuerySet -from sentry.incidents.models.alert_rule_activations import AlertRuleActivations from sentry.incidents.models.incident import Incident, IncidentStatus, IncidentTrigger -from sentry.incidents.utils.constants import INCIDENTS_SNUBA_SUBSCRIPTION_TYPE -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.models.organization import Organization from sentry.models.project import Project from sentry.models.team import Team @@ -40,7 +37,6 @@ ) from sentry.seer.anomaly_detection.delete_rule import delete_rule_in_seer from sentry.snuba.models import QuerySubscription -from sentry.snuba.subscriptions import bulk_create_snuba_subscriptions from sentry.types.actor import Actor from sentry.users.services.user import RpcUser from sentry.users.services.user.service import user_service @@ -254,56 +250,6 @@ def owner(self, actor: Actor | None) -> None: def get_audit_log_data(self) -> dict[str, Any]: return {"label": self.name} - def subscribe_projects( - self, - projects: Iterable[Project], - monitor_type: AlertRuleMonitorTypeInt = AlertRuleMonitorTypeInt.CONTINUOUS, - query_extra: str | None = None, - activation_condition: AlertRuleActivationConditionType | None = None, - activator: str | None = None, - ) -> list[QuerySubscription]: - """ - Subscribes a list of projects to the alert rule instance - :return: The list of created subscriptions - """ - - logger.info( - "Subscribing projects to alert rule", - extra={ - "alert_rule.monitor_type": self.monitor_type, - "conditional_monitor_type": monitor_type, - "query_extra": query_extra, - }, - ) - # NOTE: AlertRuleMonitorTypeInt.ACTIVATED will be conditionally subscribed given activation triggers - # On activated subscription, additional query parameters will be added to the constructed query in Snuba - created_subscriptions = [] - if self.monitor_type == monitor_type: - # NOTE: QuerySubscriptions hold reference to Projects which should match the AlertRule's project reference - created_subscriptions = bulk_create_snuba_subscriptions( - projects, - INCIDENTS_SNUBA_SUBSCRIPTION_TYPE, - self.snuba_query, - query_extra=query_extra, - ) - if self.monitor_type == AlertRuleMonitorTypeInt.ACTIVATED: - # NOTE: Activated Alert Rules are conditionally subscribed - # Meaning at time of subscription, the rule must have been activated - if not activator or activation_condition is None: - raise Exception( - "Alert activations require an activation condition and activator reference" - ) - - for subscription in created_subscriptions: - AlertRuleActivations.objects.create( - alert_rule=self, - query_subscription=subscription, - condition_type=activation_condition.value, - activator=activator, - ) - - return created_subscriptions - class AlertRuleTriggerManager(BaseManager["AlertRuleTrigger"]): CACHE_KEY = "alert_rule_triggers:alert_rule:%s" diff --git a/src/sentry/integrations/metric_alerts.py b/src/sentry/integrations/metric_alerts.py index 1a3ad9d87d7a38..52bf592e19a1e9 100644 --- a/src/sentry/integrations/metric_alerts.py +++ b/src/sentry/integrations/metric_alerts.py @@ -222,10 +222,8 @@ def metric_alert_attachment_info( text += f"\nThreshold: {alert_rule.detection_type.title()}" date_started = None - activation = None if selected_incident: date_started = selected_incident.date_started - activation = selected_incident.activation last_triggered_date = None if latest_incident: @@ -239,8 +237,4 @@ def metric_alert_attachment_info( "date_started": date_started, "last_triggered_date": last_triggered_date, "title_link": title_link, - "activator": (activation.activator if activation else ""), - "condition_type": ( - activation.condition_type if activation else None - ), # 0 = release creation, 1 = deploy creation } diff --git a/src/sentry/testutils/factories.py b/src/sentry/testutils/factories.py index 55e6e515ede327..4c70cfba39a116 100644 --- a/src/sentry/testutils/factories.py +++ b/src/sentry/testutils/factories.py @@ -42,13 +42,10 @@ query_datasets_to_type, ) from sentry.incidents.models.alert_rule import ( - AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleThresholdType, AlertRuleTriggerAction, ) -from sentry.incidents.models.alert_rule_activations import AlertRuleActivations from sentry.incidents.models.incident import ( Incident, IncidentActivity, @@ -57,7 +54,6 @@ IncidentType, TriggerStatus, ) -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.integrations.models.doc_integration import DocIntegration from sentry.integrations.models.doc_integration_avatar import DocIntegrationAvatar from sentry.integrations.models.external_actor import ExternalActor @@ -145,7 +141,7 @@ from sentry.signals import project_created from sentry.silo.base import SiloMode from sentry.snuba.dataset import Dataset -from sentry.snuba.models import QuerySubscription, QuerySubscriptionDataSourceHandler +from sentry.snuba.models import QuerySubscriptionDataSourceHandler from sentry.tempest.models import MessageType as TempestMessageType from sentry.tempest.models import TempestCredentials from sentry.testutils.outbox import outbox_runner @@ -1547,7 +1543,6 @@ def create_incident( date_closed=None, alert_rule=None, subscription=None, - activation=None, ): if not title: title = petname.generate(2, " ", letters=10).title() @@ -1567,7 +1562,6 @@ def create_incident( date_closed=timezone.now() if date_closed is not None else date_closed, type=IncidentType.ALERT_TRIGGERED.value, subscription=subscription, - activation=activation, ) for project in projects: IncidentProject.objects.create(incident=incident, project=project) @@ -1601,8 +1595,6 @@ def create_alert_rule( user=None, event_types=None, comparison_delta=None, - monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS, - activation_condition=AlertRuleActivationConditionType.RELEASE_CREATION, description=None, sensitivity=None, seasonality=None, @@ -1631,8 +1623,6 @@ def create_alert_rule( user=user, event_types=event_types, comparison_delta=comparison_delta, - monitor_type=monitor_type, - activation_condition=activation_condition, description=description, sensitivity=sensitivity, seasonality=seasonality, @@ -1644,28 +1634,6 @@ def create_alert_rule( return alert_rule - @staticmethod - @assume_test_silo_mode(SiloMode.REGION) - def create_alert_rule_activation( - alert_rule: AlertRule, - query_subscription: QuerySubscription, - metric_value: int | None = None, - finished_at: datetime | None = None, - activation_condition: AlertRuleActivationConditionType = AlertRuleActivationConditionType.RELEASE_CREATION, - ): - - with transaction.atomic(router.db_for_write(AlertRuleActivations)): - activation = AlertRuleActivations.objects.create( - alert_rule=alert_rule, - finished_at=finished_at, - metric_value=metric_value, - query_subscription=query_subscription, - condition_type=activation_condition.value, - activator="testing", - ) - - return activation - @staticmethod @assume_test_silo_mode(SiloMode.REGION) def create_alert_rule_trigger(alert_rule, label=None, alert_threshold=100): diff --git a/src/sentry/testutils/fixtures.py b/src/sentry/testutils/fixtures.py index 548284a948ab77..83346d882b640f 100644 --- a/src/sentry/testutils/fixtures.py +++ b/src/sentry/testutils/fixtures.py @@ -1,6 +1,6 @@ from __future__ import annotations -from collections.abc import Iterable, Mapping +from collections.abc import Mapping from datetime import datetime, timedelta from typing import Any @@ -10,7 +10,7 @@ from sentry.eventstore.models import Event from sentry.grouping.grouptype import ErrorGroupType -from sentry.incidents.models.alert_rule import AlertRule, AlertRuleMonitorTypeInt +from sentry.incidents.models.alert_rule import AlertRule from sentry.integrations.models.integration import Integration from sentry.integrations.models.organization_integration import OrganizationIntegration from sentry.models.activity import Activity @@ -26,7 +26,6 @@ from sentry.monitors.models import Monitor, MonitorType, ScheduleType from sentry.organizations.services.organization import RpcOrganization from sentry.silo.base import SiloMode -from sentry.snuba.models import QuerySubscription from sentry.tempest.models import TempestCredentials from sentry.testutils.factories import Factories from sentry.testutils.helpers.datetime import before_now @@ -389,36 +388,6 @@ def create_alert_rule(self, organization=None, projects=None, *args, **kwargs) - projects = [self.project] return Factories.create_alert_rule(organization, projects, *args, **kwargs) - def create_alert_rule_activation( - self, - alert_rule: AlertRule | None = None, - query_subscriptions: Iterable[QuerySubscription] | None = None, - project=None, - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED, - activator=None, - activation_condition=None, - *args, - **kwargs, - ): - if not alert_rule: - alert_rule = self.create_alert_rule(monitor_type=monitor_type) - if not query_subscriptions: - projects = [project] if project else [self.project] - # subscribing an activated alert rule will create an activation - query_subscriptions = alert_rule.subscribe_projects( - projects=projects, - monitor_type=monitor_type, - activation_condition=activation_condition, - activator=activator, - ) - - created_activations = [] - for sub in query_subscriptions: - created_activations.append( - Factories.create_alert_rule_activation(alert_rule, sub, *args, **kwargs) - ) - return created_activations - def create_alert_rule_trigger(self, alert_rule=None, *args, **kwargs): if not alert_rule: alert_rule = self.create_alert_rule() diff --git a/src/sentry/testutils/helpers/backups.py b/src/sentry/testutils/helpers/backups.py index 57ce956f4e6018..8897197348d186 100644 --- a/src/sentry/testutils/helpers/backups.py +++ b/src/sentry/testutils/helpers/backups.py @@ -44,7 +44,10 @@ from sentry.backup.validate import validate from sentry.data_secrecy.models import DataSecrecyWaiver from sentry.db.models.paranoia import ParanoidModel -from sentry.incidents.models.alert_rule import AlertRuleMonitorTypeInt +from sentry.incidents.models.alert_rule_activations import ( + AlertRuleActivationCondition, + AlertRuleActivations, +) from sentry.incidents.models.incident import ( IncidentActivity, IncidentSnapshot, @@ -524,21 +527,16 @@ def create_exhaustive_organization( trigger = self.create_alert_rule_trigger(alert_rule=alert) assert alert.snuba_query is not None self.create_alert_rule_trigger_action(alert_rule_trigger=trigger) - activated_alert = self.create_alert_rule( - organization=org, - projects=[project], - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED, - activation_condition=AlertRuleActivationConditionType.RELEASE_CREATION, - ) - self.create_alert_rule_activation( - alert_rule=activated_alert, - project=project, + + AlertRuleActivations.objects.create( + alert_rule=alert, + finished_at=None, metric_value=100, - activator="testing exhaustive", - activation_condition=AlertRuleActivationConditionType.RELEASE_CREATION, + query_subscription=None, + condition_type=AlertRuleActivationConditionType.RELEASE_CREATION.value, + activator="testing", ) - activated_trigger = self.create_alert_rule_trigger(alert_rule=activated_alert) - self.create_alert_rule_trigger_action(alert_rule_trigger=activated_trigger) + AlertRuleActivationCondition.objects.create(alert_rule=alert, condition_type=None) # Incident* incident = self.create_incident(org, [project]) diff --git a/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py b/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py index 0c0810830d7dcc..1953d3ee27d76c 100644 --- a/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py +++ b/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py @@ -29,7 +29,6 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleSeasonality, AlertRuleSensitivity, AlertRuleStatus, @@ -39,7 +38,6 @@ ) from sentry.incidents.models.incident import Incident, IncidentStatus from sentry.incidents.serializers import AlertRuleSerializer -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.integrations.slack.tasks.find_channel_id_for_alert_rule import ( find_channel_id_for_alert_rule, ) @@ -655,40 +653,6 @@ def test_simple(self): == list(audit_log_entry)[0].ip_address ) - def test_monitor_type_with_condition(self): - self.create_member( - user=self.user, organization=self.organization, role="owner", teams=[self.team] - ) - - self.login_as(self.user) - alert_rule = self.alert_rule - serialized_alert_rule = self.get_serialized_alert_rule() - serialized_alert_rule["monitorType"] = AlertRuleMonitorTypeInt.ACTIVATED - serialized_alert_rule["activationCondition"] = ( - AlertRuleActivationConditionType.RELEASE_CREATION.value - ) - with ( - outbox_runner(), - self.feature(["organizations:incidents", "organizations:activated-alert-rules"]), - ): - resp = self.get_success_response( - self.organization.slug, alert_rule.id, **serialized_alert_rule - ) - alert_rule = AlertRule.objects.get(id=resp.data["id"]) - alert_rule.monitorType = AlertRuleMonitorTypeInt.ACTIVATED - alert_rule.activationCondition = AlertRuleActivationConditionType.RELEASE_CREATION.value - alert_rule.date_modified = resp.data["dateModified"] - assert resp.data == serialize(alert_rule) - - # TODO: determine how to convert activated alert into continuous alert and vice versa (see logic.py) - # requires creating/disabling activations accordingly - # assert resp.data["monitorType"] == AlertRuleMonitorTypeInt.ACTIVATED - # assert ( - # resp.data["activationCondition"] - # == AlertRuleActivationConditionType.RELEASE_CREATION.value - # ) - assert resp.data["dateModified"] > serialized_alert_rule["dateModified"] - def test_not_updated_fields(self): self.create_member( user=self.user, organization=self.organization, role="owner", teams=[self.team] diff --git a/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py b/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py index b39cae4d34d004..41f6fc2be77068 100644 --- a/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py +++ b/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py @@ -23,7 +23,6 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleSeasonality, AlertRuleSensitivity, AlertRuleThresholdType, @@ -98,7 +97,6 @@ def alert_rule_dict(self): "projects": [self.project.slug], "owner": self.user.id, "name": "JustAValidTestRule", - "activations": [], } @cached_property @@ -131,7 +129,6 @@ def dynamic_alert_rule_dict(self): "projects": [self.project.slug], "owner": self.user.id, "name": "JustAValidTestRule", - "activations": [], } @@ -179,7 +176,7 @@ def test_no_feature(self): def test_response_headers(self): self.create_team(organization=self.organization, members=[self.user]) - self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) + self.create_alert_rule() self.login_as(self.user) with self.feature("organizations:incidents"): diff --git a/tests/sentry/incidents/test_logic.py b/tests/sentry/incidents/test_logic.py index c5e322d6d6c459..3234f4e2ab6b63 100644 --- a/tests/sentry/incidents/test_logic.py +++ b/tests/sentry/incidents/test_logic.py @@ -59,7 +59,6 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleSeasonality, AlertRuleSensitivity, AlertRuleStatus, @@ -78,7 +77,6 @@ IncidentType, TriggerStatus, ) -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.integrations.discord.utils.channel import ChannelType from sentry.integrations.models.organization_integration import OrganizationIntegration from sentry.integrations.pagerduty.utils import add_service @@ -375,68 +373,6 @@ class _DynamicMetricAlertSettings(TypedDict): } def test_create_alert_rule(self): - class _Kwargs(TypedDict, total=False): - monitor_type: AlertRuleMonitorTypeInt - activation_condition: AlertRuleActivationConditionType - - # pytest parametrize does not work in TestCase subclasses, so hack around this - # TODO: backfill projects so all monitor_types include 'projects' fk - for monitor_type in [ - None, - AlertRuleMonitorTypeInt.CONTINUOUS, - AlertRuleMonitorTypeInt.ACTIVATED, - ]: - name = "hello" - query = "level:error" - aggregate = "count(*)" - time_window = 10 - threshold_type = AlertRuleThresholdType.ABOVE - resolve_threshold = 10 - threshold_period = 1 - event_types = [SnubaQueryEventType.EventType.ERROR] - kwargs: _Kwargs = ( - { - "monitor_type": monitor_type, - "activation_condition": AlertRuleActivationConditionType.RELEASE_CREATION, - } - if monitor_type - else {} - ) - alert_rule = create_alert_rule( - self.organization, - [self.project], - name, - query, - aggregate, - time_window, - threshold_type, - threshold_period, - resolve_threshold=resolve_threshold, - event_types=event_types, - **kwargs, - ) - assert alert_rule.name == name - assert alert_rule.user_id is None - assert alert_rule.team_id is None - assert alert_rule.status == AlertRuleStatus.PENDING.value - assert alert_rule.snuba_query is not None - if alert_rule.snuba_query.subscriptions.exists(): - assert alert_rule.snuba_query.subscriptions.get().project == self.project - assert alert_rule.snuba_query.subscriptions.all().count() == 1 - assert alert_rule.snuba_query.type == SnubaQuery.Type.ERROR.value - assert alert_rule.snuba_query.dataset == Dataset.Events.value - assert alert_rule.snuba_query.query == query - assert alert_rule.snuba_query.aggregate == aggregate - assert alert_rule.snuba_query.time_window == time_window * 60 - assert alert_rule.snuba_query.resolution == DEFAULT_ALERT_RULE_RESOLUTION * 60 - assert set(alert_rule.snuba_query.event_types) == set(event_types) - assert alert_rule.threshold_type == threshold_type.value - assert alert_rule.resolve_threshold == resolve_threshold - assert alert_rule.threshold_period == threshold_period - # We now create an AlertRuleProject for all rule monitor types - assert alert_rule.projects.all().count() == 1 - - def test_create_activated_alert_rule_errors_without_condition(self): name = "hello" query = "level:error" aggregate = "count(*)" @@ -445,21 +381,37 @@ def test_create_activated_alert_rule_errors_without_condition(self): resolve_threshold = 10 threshold_period = 1 event_types = [SnubaQueryEventType.EventType.ERROR] - - with pytest.raises(ValidationError): - create_alert_rule( - self.organization, - [self.project], - name, - query, - aggregate, - time_window, - threshold_type, - threshold_period, - resolve_threshold=resolve_threshold, - event_types=event_types, - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED, - ) + alert_rule = create_alert_rule( + self.organization, + [self.project], + name, + query, + aggregate, + time_window, + threshold_type, + threshold_period, + resolve_threshold=resolve_threshold, + event_types=event_types, + ) + assert alert_rule.name == name + assert alert_rule.user_id is None + assert alert_rule.team_id is None + assert alert_rule.status == AlertRuleStatus.PENDING.value + assert alert_rule.snuba_query is not None + if alert_rule.snuba_query.subscriptions.exists(): + assert alert_rule.snuba_query.subscriptions.get().project == self.project + assert alert_rule.snuba_query.subscriptions.all().count() == 1 + assert alert_rule.snuba_query.type == SnubaQuery.Type.ERROR.value + assert alert_rule.snuba_query.dataset == Dataset.Events.value + assert alert_rule.snuba_query.query == query + assert alert_rule.snuba_query.aggregate == aggregate + assert alert_rule.snuba_query.time_window == time_window * 60 + assert alert_rule.snuba_query.resolution == DEFAULT_ALERT_RULE_RESOLUTION * 60 + assert set(alert_rule.snuba_query.event_types) == set(event_types) + assert alert_rule.threshold_type == threshold_type.value + assert alert_rule.resolve_threshold == resolve_threshold + assert alert_rule.threshold_period == threshold_period + assert alert_rule.projects.all().count() == 1 def test_ignore(self): name = "hello" diff --git a/tests/sentry/incidents/test_subscription_processor.py b/tests/sentry/incidents/test_subscription_processor.py index f0eb09733d22b6..281be19fd0c732 100644 --- a/tests/sentry/incidents/test_subscription_processor.py +++ b/tests/sentry/incidents/test_subscription_processor.py @@ -24,7 +24,6 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleSeasonality, AlertRuleSensitivity, AlertRuleStatus, @@ -227,7 +226,6 @@ def create_rule_trigger_and_action(self, projects: list[Project]): threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, - monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS, event_types=[ SnubaQueryEventType.EventType.ERROR, SnubaQueryEventType.EventType.DEFAULT,