diff --git a/src/sentry/incidents/endpoints/organization_alert_rule_details.py b/src/sentry/incidents/endpoints/organization_alert_rule_details.py index 0aeea3a1fb0df0..293d7d998f2126 100644 --- a/src/sentry/incidents/endpoints/organization_alert_rule_details.py +++ b/src/sentry/incidents/endpoints/organization_alert_rule_details.py @@ -213,17 +213,6 @@ class OrganizationAlertRuleDetailsPutSerializer(serializers.Serializer): required=False, allow_null=True, help_text="The ID of the team or user that owns the rule." ) thresholdPeriod = serializers.IntegerField(required=False, default=1, min_value=1, max_value=20) - monitorType = serializers.IntegerField( - required=False, - min_value=0, - help_text="Monitor type represents whether the alert rule is actively being monitored or is monitored given a specific activation condition.", - ) - activationCondition = serializers.IntegerField( - required=False, - allow_null=True, - min_value=0, - help_text="Optional int that represents a trigger condition for when to start monitoring", - ) @extend_schema(tags=["Alerts"]) diff --git a/src/sentry/incidents/endpoints/organization_alert_rule_index.py b/src/sentry/incidents/endpoints/organization_alert_rule_index.py index db45347717d093..38badddd8dfcd8 100644 --- a/src/sentry/incidents/endpoints/organization_alert_rule_index.py +++ b/src/sentry/incidents/endpoints/organization_alert_rule_index.py @@ -78,10 +78,6 @@ def fetch_metric_alert( if not features.has("organizations:performance-view", organization): alert_rules = alert_rules.filter(snuba_query__dataset=Dataset.Events.value) - monitor_type = request.GET.get("monitor_type", None) - if monitor_type is not None: - alert_rules = alert_rules.filter(monitor_type=monitor_type) - response = self.paginate( request, queryset=alert_rules, @@ -186,10 +182,6 @@ def get(self, request: Request, organization) -> Response: alert_rules = AlertRule.objects.fetch_for_organization(organization, projects) - monitor_type = request.GET.get("monitor_type", None) - if monitor_type is not None: - alert_rules = alert_rules.filter(monitor_type=monitor_type) - issue_rules = Rule.objects.filter( status__in=[ObjectStatus.ACTIVE, ObjectStatus.DISABLED], source__in=[RuleSource.ISSUE], @@ -410,17 +402,6 @@ class OrganizationAlertRuleIndexPostSerializer(serializers.Serializer): required=False, allow_null=True, help_text="The ID of the team or user that owns the rule." ) thresholdPeriod = serializers.IntegerField(required=False, default=1, min_value=1, max_value=20) - monitorType = serializers.IntegerField( - required=False, - min_value=0, - help_text="Monitor type represents whether the alert rule is actively being monitored or is monitored given a specific activation condition.", - ) - activationCondition = serializers.IntegerField( - required=False, - allow_null=True, - min_value=0, - help_text="Optional int that represents a trigger condition for when to start monitoring", - ) @extend_schema(tags=["Alerts"]) diff --git a/src/sentry/incidents/endpoints/serializers/alert_rule.py b/src/sentry/incidents/endpoints/serializers/alert_rule.py index 9d6e31d3c65935..3514e60df0ae43 100644 --- a/src/sentry/incidents/endpoints/serializers/alert_rule.py +++ b/src/sentry/incidents/endpoints/serializers/alert_rule.py @@ -6,8 +6,7 @@ from datetime import datetime from typing import Any, TypedDict -from django.db.models import F, Max, Q, Window, prefetch_related_objects -from django.db.models.functions import RowNumber +from django.db.models import Max, Q, prefetch_related_objects from drf_spectacular.utils import extend_schema_serializer from sentry import features @@ -20,7 +19,6 @@ AlertRuleTrigger, AlertRuleTriggerAction, ) -from sentry.incidents.models.alert_rule_activations import AlertRuleActivations from sentry.incidents.models.incident import Incident from sentry.models.rule import Rule from sentry.models.rulesnooze import RuleSnooze @@ -88,9 +86,6 @@ class AlertRuleSerializerResponse(AlertRuleSerializerResponseOptional): dateModified: datetime dateCreated: datetime createdBy: dict - monitorType: int - activations: list[dict] - activationCondition: int | None description: str detectionType: str @@ -171,18 +166,6 @@ def get_attrs( result[alert_rule]["errors"] = errors alert_rule_triggers.append(serialized) - alert_activations_ranked = AlertRuleActivations.objects.annotate( - rank=Window( - expression=RowNumber(), - partition_by=[F("alert_rule_id")], - order_by=F("date_added").desc(), - ) - ) - activations_qs = alert_activations_ranked.filter(alert_rule__in=item_list, rank__lte=10) - activations_by_alert_rule_id = defaultdict(list) - for activation in activations_qs: - activations_by_alert_rule_id[activation.alert_rule_id].append(activation) - alert_rule_projects = set() for alert_rule in alert_rules.values(): if alert_rule.projects.exists(): @@ -227,13 +210,6 @@ def get_attrs( result[alert_rules[rule_activity.alert_rule_id]]["created_by"] = created_by for item in item_list: - activations = sorted( - activations_by_alert_rule_id.get(item.id, []), - key=lambda x: x.date_added, - reverse=True, - ) - result[item]["activations"] = serialize(activations, **kwargs) - if item.user_id or item.team_id: actor = item.owner if actor: @@ -283,7 +259,6 @@ def serialize( aggregate = translate_aggregate_field( obj.snuba_query.aggregate, reverse=True, allow_mri=allow_mri ) - condition_type = obj.activation_condition.values_list("condition_type", flat=True).first() data: AlertRuleSerializerResponse = { "id": str(obj.id), @@ -310,9 +285,6 @@ def serialize( "dateModified": obj.date_modified, "dateCreated": obj.date_added, "createdBy": attrs.get("created_by", None), - "monitorType": obj.monitor_type, - "activationCondition": condition_type, - "activations": attrs.get("activations", None), "description": obj.description if obj.description is not None else "", "sensitivity": obj.sensitivity, "seasonality": obj.seasonality, diff --git a/src/sentry/incidents/endpoints/serializers/incident.py b/src/sentry/incidents/endpoints/serializers/incident.py index 4df9bc2015ab85..9bf4740d6ecb19 100644 --- a/src/sentry/incidents/endpoints/serializers/incident.py +++ b/src/sentry/incidents/endpoints/serializers/incident.py @@ -35,9 +35,6 @@ def get_attrs(self, item_list, user, **kwargs): for incident in item_list: results[incident] = {"projects": incident_projects.get(incident.id, [])} results[incident]["alert_rule"] = alert_rules.get(str(incident.alert_rule.id)) # type: ignore[assignment] - results[incident]["activation"] = ( - serialize(incident.activation) if incident.activation else [] - ) if "activities" in self.expand: # There could be many activities. An incident could seesaw between error/warning for a long period. @@ -68,7 +65,6 @@ def serialize(self, obj, attrs, user, **kwargs): "dateDetected": obj.date_detected, "dateCreated": obj.date_added, "dateClosed": date_closed, - "activation": attrs.get("activation", []), } diff --git a/src/sentry/incidents/serializers/alert_rule.py b/src/sentry/incidents/serializers/alert_rule.py index 4c0c6ddac49405..50e3afd03fce0a 100644 --- a/src/sentry/incidents/serializers/alert_rule.py +++ b/src/sentry/incidents/serializers/alert_rule.py @@ -37,11 +37,9 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleThresholdType, AlertRuleTrigger, ) -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.snuba.dataset import Dataset from sentry.snuba.entity_subscription import ( ENTITY_TIME_COLUMNS, @@ -96,10 +94,7 @@ class AlertRuleSerializer(CamelSnakeModelSerializer[AlertRule]): # This will be set to required=True once the frontend starts sending it. owner = ActorField(required=False, allow_null=True) - monitor_type = serializers.IntegerField(required=False, min_value=0) - activation_condition = serializers.IntegerField(required=False, allow_null=True, min_value=0) description = serializers.CharField(required=False, allow_blank=True) - sensitivity = serializers.CharField(required=False, allow_null=True) seasonality = serializers.CharField(required=False, allow_null=True) detection_type = serializers.CharField(required=False, default=AlertRuleDetectionType.STATIC) @@ -122,8 +117,6 @@ class Meta: "projects", "triggers", "event_types", - "monitor_type", - "activation_condition", "description", "sensitivity", "seasonality", @@ -217,28 +210,6 @@ def validate_threshold_type(self, threshold_type): % [item.value for item in AlertRuleThresholdType] ) - def validate_monitor_type(self, monitor_type): - if monitor_type > 0 and not features.has( - "organizations:activated-alert-rules", - self.context["organization"], - actor=self.context.get("user", None), - ): - raise serializers.ValidationError("Invalid monitor type") - - return AlertRuleMonitorTypeInt(monitor_type) - - def validate_activation_condition(self, activation_condition): - if activation_condition is None: - return activation_condition - - try: - return AlertRuleActivationConditionType(activation_condition) - except ValueError: - raise serializers.ValidationError( - "Invalid activation condition, valid values are %s" - % [item.value for item in AlertRuleActivationConditionType] - ) - def validate(self, data): """ Performs validation on an alert rule's data. @@ -545,12 +516,6 @@ def update(self, instance, validated_data): triggers = validated_data.pop("triggers") if "id" in validated_data: validated_data.pop("id") - if "monitor_type" in validated_data: - """ - TODO: enable monitor type editing - requires creating/disabling activations accordingly - """ - validated_data.pop("monitor_type") with transaction.atomic(router.db_for_write(AlertRule)): try: alert_rule = update_alert_rule( diff --git a/tests/sentry/incidents/endpoints/serializers/test_alert_rule.py b/tests/sentry/incidents/endpoints/serializers/test_alert_rule.py index b132d2a8fa977a..8082810c0864f9 100644 --- a/tests/sentry/incidents/endpoints/serializers/test_alert_rule.py +++ b/tests/sentry/incidents/endpoints/serializers/test_alert_rule.py @@ -13,12 +13,10 @@ from sentry.incidents.models.alert_rule import ( AlertRule, AlertRuleDetectionType, - AlertRuleMonitorTypeInt, AlertRuleProjects, AlertRuleThresholdType, AlertRuleTriggerAction, ) -from sentry.incidents.utils.types import AlertRuleActivationConditionType from sentry.models.rule import Rule from sentry.snuba.models import SnubaQueryEventType from sentry.testutils.cases import APITestCase, TestCase @@ -145,70 +143,21 @@ def test_triggers(self): assert result[0]["triggers"] == [serialize(trigger)] assert result[1]["triggers"] == [] - def test_activations(self): - alert_rule = self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) - activated_alert_rule = self.create_alert_rule( - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED - ) - other_alert_rule = self.create_alert_rule() - - activations = self.create_alert_rule_activation( - alert_rule=alert_rule, monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS - ) - activated_alert_rule.subscribe_projects( - projects=[self.project], - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED, - activation_condition=AlertRuleActivationConditionType.RELEASE_CREATION, - activator="testing", - ) - activated_alert_rule.refresh_from_db() - - result = serialize([alert_rule, other_alert_rule, activated_alert_rule]) - assert result[0]["activations"] == serialize(activations) - assert result[1]["activations"] == [] - assert result[2]["activations"] == serialize(list(activated_alert_rule.activations.all())) - assert ( - result[2]["activationCondition"] - == AlertRuleActivationConditionType.RELEASE_CREATION.value - ) - - def test_truncated_activations(self): - alert_rule = self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) - alert_rule2 = self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) - for i in range(11): - self.create_alert_rule_activation( - alert_rule=alert_rule, monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS - ) - if i % 2 == 0: - self.create_alert_rule_activation( - alert_rule=alert_rule2, monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS - ) - result = serialize([alert_rule, alert_rule2]) - assert len(result[0]["activations"]) == 10 - assert len(result[1]["activations"]) == 6 - def test_projects(self): regular_alert_rule = self.create_alert_rule() - activated_alert_rule = self.create_alert_rule( - monitor_type=AlertRuleMonitorTypeInt.ACTIVATED - ) alert_rule_no_projects = self.create_alert_rule() AlertRuleProjects.objects.filter(alert_rule_id=alert_rule_no_projects.id).delete() - assert activated_alert_rule.projects assert regular_alert_rule.projects assert not alert_rule_no_projects.projects.exists() - result = serialize([regular_alert_rule, activated_alert_rule, alert_rule_no_projects]) + result = serialize([regular_alert_rule, alert_rule_no_projects]) assert result[0]["projects"] == [ project.slug for project in regular_alert_rule.projects.all() ] - assert result[1]["projects"] == [ - project.slug for project in activated_alert_rule.projects.all() - ] # NOTE: we are now _only_ referencing alert_rule.projects fk (AlertRuleProjects) - assert result[2]["projects"] == [ + assert result[1]["projects"] == [ project.slug for project in alert_rule_no_projects.projects.all() ] 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 444d9bb6648b0c..b39cae4d34d004 100644 --- a/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py +++ b/tests/sentry/incidents/endpoints/test_organization_alert_rule_index.py @@ -30,7 +30,6 @@ AlertRuleTrigger, AlertRuleTriggerAction, ) -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, ) @@ -178,44 +177,17 @@ def test_no_feature(self): resp = self.get_response(self.organization.slug) assert resp.status_code == 404 - def test_filter_by_monitor_type(self): - self.create_team(organization=self.organization, members=[self.user]) - alert_rule1 = self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.ACTIVATED) - alert_rule2 = self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) - self.login_as(self.user) - - params = {"monitor_type": 1} - with self.feature("organizations:incidents"): - resp = self.get_response(self.organization.slug, **params) - - assert serialize([alert_rule2]) not in resp.data - assert resp.data == serialize([alert_rule1]) - def test_response_headers(self): self.create_team(organization=self.organization, members=[self.user]) - self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.ACTIVATED) self.create_alert_rule(monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS) self.login_as(self.user) with self.feature("organizations:incidents"): resp = self.get_response(self.organization.slug) - assert resp[ALERT_RULES_COUNT_HEADER] == "2" + assert resp[ALERT_RULES_COUNT_HEADER] == "1" assert resp[MAX_QUERY_SUBSCRIPTIONS_HEADER] == "1000" - def test_simple_with_activation(self): - self.create_team(organization=self.organization, members=[self.user]) - alert_rule = self.create_alert_rule() - self.create_alert_rule_activation( - alert_rule=alert_rule, monitor_type=AlertRuleMonitorTypeInt.CONTINUOUS - ) - - self.login_as(self.user) - with self.feature("organizations:incidents"): - resp = self.get_success_response(self.organization.slug) - - assert resp.data == serialize([alert_rule]) - @freeze_time() class AlertRuleCreateEndpointTest(AlertRuleIndexBase, SnubaTestCase): @@ -425,37 +397,6 @@ def test_anomaly_detection_alert_validation_error(self): assert not AlertRule.objects.filter(detection_type=AlertRuleDetectionType.DYNAMIC).exists() assert resp.data[0] == INVALID_TIME_WINDOW - def test_monitor_type_with_condition(self): - data = { - **self.alert_rule_dict, - "monitorType": AlertRuleMonitorTypeInt.ACTIVATED, - "activationCondition": AlertRuleActivationConditionType.RELEASE_CREATION.value, - } - with ( - outbox_runner(), - self.feature(["organizations:incidents"]), - ): - err_resp = self.get_error_response( - self.organization.slug, - method=responses.POST, - status_code=status.HTTP_400_BAD_REQUEST, - **data, - ).json() - assert err_resp == {"monitorType": ["Invalid monitor type"]} - - with ( - outbox_runner(), - self.feature(["organizations:incidents", "organizations:activated-alert-rules"]), - ): - resp = self.get_success_response( - self.organization.slug, - status_code=201, - **data, - ) - assert "id" in resp.data - alert_rule = AlertRule.objects.get(id=resp.data["id"]) - assert resp.data == serialize(alert_rule, self.user) - def test_multiple_projects(self): new_project = self.create_project() data = {**self.alert_rule_dict, "projects": [self.project.slug, new_project.slug]}