Skip to content

Commit

Permalink
chore(alerts): Remove activated alerts from serializers
Browse files Browse the repository at this point in the history
  • Loading branch information
ceorourke committed Jan 6, 2025
1 parent 8ff2196 commit fa9c9a7
Show file tree
Hide file tree
Showing 7 changed files with 4 additions and 211 deletions.
11 changes: 0 additions & 11 deletions src/sentry/incidents/endpoints/organization_alert_rule_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
19 changes: 0 additions & 19 deletions src/sentry/incidents/endpoints/organization_alert_rule_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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"])
Expand Down
30 changes: 1 addition & 29 deletions src/sentry/incidents/endpoints/serializers/alert_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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():
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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),
Expand All @@ -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,
Expand Down
4 changes: 0 additions & 4 deletions src/sentry/incidents/endpoints/serializers/incident.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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", []),
}


Expand Down
35 changes: 0 additions & 35 deletions src/sentry/incidents/serializers/alert_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -122,8 +117,6 @@ class Meta:
"projects",
"triggers",
"event_types",
"monitor_type",
"activation_condition",
"description",
"sensitivity",
"seasonality",
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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(
Expand Down
55 changes: 2 additions & 53 deletions tests/sentry/incidents/endpoints/serializers/test_alert_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
]

Expand Down
Loading

0 comments on commit fa9c9a7

Please sign in to comment.