From 7ed6a36f3a055afd42eb7ac19ed3ff0a708a4e67 Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Mon, 10 Nov 2025 11:10:44 -0800 Subject: [PATCH 1/6] saving work --- .../serializers/workflow_engine_incident.py | 110 ++++++------------ 1 file changed, 36 insertions(+), 74 deletions(-) diff --git a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py index 8aeb706abcd59b..b23bda406d3761 100644 --- a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py +++ b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py @@ -1,33 +1,21 @@ -from collections import defaultdict from collections.abc import Mapping, Sequence -from typing import Any, DefaultDict +from typing import Any from django.contrib.auth.models import AnonymousUser -from django.db.models import Subquery -from sentry.api.serializers import Serializer, serialize +from sentry.api.serializers import Serializer from sentry.incidents.endpoints.serializers.incident import ( DetailedIncidentSerializerResponse, - IncidentSerializer, IncidentSerializerResponse, ) -from sentry.incidents.models.incident import Incident +from sentry.incidents.endpoints.serializers.utils import get_object_id_from_fake_id +from sentry.incidents.models.incident import IncidentStatusMethod, IncidentType from sentry.models.groupopenperiod import GroupOpenPeriod from sentry.snuba.entity_subscription import apply_dataset_query_conditions from sentry.snuba.models import QuerySubscription, SnubaQuery from sentry.users.models.user import User from sentry.users.services.user.model import RpcUser -from sentry.workflow_engine.models import ( - Action, - DataCondition, - DataConditionGroupAction, - DataSourceDetector, - Detector, - DetectorWorkflow, - IncidentGroupOpenPeriod, - WorkflowDataConditionGroup, -) -from sentry.workflow_engine.models.workflow_action_group_status import WorkflowActionGroupStatus +from sentry.workflow_engine.models import DataSourceDetector, Detector, IncidentGroupOpenPeriod class WorkflowEngineIncidentSerializer(Serializer): @@ -37,59 +25,7 @@ def __init__(self, expand=None): def get_open_periods_to_detectors( self, open_periods: Sequence[GroupOpenPeriod] ) -> dict[GroupOpenPeriod, Detector]: - wf_action_group_statuses = WorkflowActionGroupStatus.objects.filter( - group__in=[open_period.group for open_period in open_periods] - ) - open_periods_to_actions: DefaultDict[GroupOpenPeriod, Action] = defaultdict() - for open_period in open_periods: - for wf_action_group_status in wf_action_group_statuses: - if wf_action_group_status.group == open_period.group: - open_periods_to_actions[open_period] = wf_action_group_status.action - break - - dcgas = DataConditionGroupAction.objects.filter( - action__in=list(open_periods_to_actions.values()) - ) - open_periods_to_condition_group: DefaultDict[GroupOpenPeriod, DataConditionGroupAction] = ( - defaultdict() - ) - for open_period, action in open_periods_to_actions.items(): - for dcga in dcgas: - if dcga.action == action: - open_periods_to_condition_group[open_period] = dcga - break - - action_filters = DataCondition.objects.filter( - condition_group__in=[dcga.condition_group for dcga in dcgas] - ) - open_period_to_action_filters: DefaultDict[GroupOpenPeriod, DataCondition] = defaultdict() - for open_period, dcga in open_periods_to_condition_group.items(): - for action_filter in action_filters: - if action_filter.condition_group == dcga.condition_group: - open_period_to_action_filters[open_period] = action_filter - break - - workflow_dcgs = WorkflowDataConditionGroup.objects.filter( - condition_group__in=Subquery(action_filters.values("condition_group")) - ) - - open_periods_to_workflow_dcgs: DefaultDict[GroupOpenPeriod, WorkflowDataConditionGroup] = ( - defaultdict() - ) - for open_period, action_filter in open_period_to_action_filters.items(): - for workflow_dcg in workflow_dcgs: - if workflow_dcg.condition_group == action_filter.condition_group: - open_periods_to_workflow_dcgs[open_period] = workflow_dcg - - detector_workflows = DetectorWorkflow.objects.filter( - workflow__in=Subquery(workflow_dcgs.values("workflow")) - ) - open_periods_to_detectors: DefaultDict[GroupOpenPeriod, Detector] = defaultdict() - for open_period, workflow_dcg in open_periods_to_workflow_dcgs.items(): - for detector_workflow in detector_workflows: - if detector_workflow.workflow == workflow_dcg.workflow: - open_periods_to_detectors[open_period] = detector_workflow.detector - break + open_periods_to_detectors = {} return open_periods_to_detectors @@ -103,10 +39,36 @@ def serialize( """ Temporary serializer to take a GroupOpenPeriod and serialize it for the old incident endpoint """ - incident = Incident.objects.get( - id=IncidentGroupOpenPeriod.objects.get(group_open_period=obj).incident_id - ) - return serialize(incident, user=user, serializer=IncidentSerializer(expand=self.expand)) + try: + igop = IncidentGroupOpenPeriod.objects.get(group_open_period=obj) + incident_id = igop.incident_id + incident_identifier = igop.incident_identifier + except IncidentGroupOpenPeriod.DoesNotExist: + incident_id = get_object_id_from_fake_id(obj.id) + incident_identifier = incident_id + + # TODO: get event time using offset + date_closed = obj.date_ended.replace(second=0, microsecond=0) if obj.date_ended else None + return { + "id": str(incident_id), + "identifier": str(incident_identifier), + "organizationId": str(obj.project.organization.id), + "projects": attrs["projects"], + "alertRule": attrs["alert_rule"], + "activities": attrs["activities"] if "activities" in self.expand else None, + "status": self.get_incident_status(obj.group.priority, obj.date_ended), + "statusMethod": ( + IncidentStatusMethod.RULE_TRIGGERED.value + if not date_closed + else IncidentStatusMethod.RULE_UPDATED.value + ), + "type": IncidentType.ALERT_TRIGGERED.value, + "title": obj.group.title, + "dateStarted": obj.date_started, + "dateDetected": obj.date_started, + "dateCreated": obj.date_added, + "dateClosed": date_closed, + } class WorkflowEngineDetailedIncidentSerializer(WorkflowEngineIncidentSerializer): From 11027dd9b017f8ec6df51e99cab873534c202677 Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Mon, 10 Nov 2025 16:19:53 -0800 Subject: [PATCH 2/6] implemented but not tested --- .../serializers/workflow_engine_incident.py | 113 +++++++++++++++++- 1 file changed, 107 insertions(+), 6 deletions(-) diff --git a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py index b23bda406d3761..e2f124a9a6c2ee 100644 --- a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py +++ b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py @@ -1,31 +1,132 @@ +from collections import defaultdict from collections.abc import Mapping, Sequence -from typing import Any +from datetime import datetime +from typing import Any, ClassVar, DefaultDict from django.contrib.auth.models import AnonymousUser -from sentry.api.serializers import Serializer +from sentry.api.serializers import Serializer, serialize from sentry.incidents.endpoints.serializers.incident import ( DetailedIncidentSerializerResponse, IncidentSerializerResponse, ) -from sentry.incidents.endpoints.serializers.utils import get_object_id_from_fake_id -from sentry.incidents.models.incident import IncidentStatusMethod, IncidentType +from sentry.incidents.endpoints.serializers.utils import get_fake_id_from_object_id +from sentry.incidents.models.incident import IncidentStatus, IncidentStatusMethod, IncidentType from sentry.models.groupopenperiod import GroupOpenPeriod +from sentry.models.groupopenperiodactivity import GroupOpenPeriodActivity from sentry.snuba.entity_subscription import apply_dataset_query_conditions from sentry.snuba.models import QuerySubscription, SnubaQuery +from sentry.types.group import PriorityLevel from sentry.users.models.user import User from sentry.users.services.user.model import RpcUser -from sentry.workflow_engine.models import DataSourceDetector, Detector, IncidentGroupOpenPeriod +from sentry.workflow_engine.endpoints.serializers.group_open_period_serializer import ( + GroupOpenPeriodActivitySerializer, +) +from sentry.workflow_engine.models import ( + AlertRuleDetector, + DataSourceDetector, + Detector, + DetectorGroup, + IncidentGroupOpenPeriod, +) class WorkflowEngineIncidentSerializer(Serializer): def __init__(self, expand=None): self.expand = expand or [] + priority_to_incident_status: ClassVar[dict[int, int]] = { + PriorityLevel.HIGH.value: IncidentStatus.CRITICAL.value, + PriorityLevel.MEDIUM.value: IncidentStatus.WARNING.value, + } + + def get_incident_status(self, priority: int | None, date_ended: datetime | None) -> int: + if priority is None: + raise ValueError("Priority is required to get an incident status") + + if date_ended: + return IncidentStatus.CLOSED.value + + return self.priority_to_incident_status[priority] + + def get_attrs( + self, + item_list: Sequence[GroupOpenPeriod], + user: User | RpcUser | AnonymousUser, + **kwargs: Any, + ) -> defaultdict[GroupOpenPeriod, dict[str, Any]]: + + from sentry.incidents.endpoints.serializers.workflow_engine_detector import ( + WorkflowEngineDetectorSerializer, + ) + + results: DefaultDict[GroupOpenPeriod, dict[str, Any]] = defaultdict() + open_periods_to_detectors = self.get_open_periods_to_detectors(item_list) + alert_rules = { + alert_rule["id"]: alert_rule # we are serializing detectors to look like alert rules + for alert_rule in serialize( + list(open_periods_to_detectors.values()), + user, + WorkflowEngineDetectorSerializer(expand=self.expand), + ) + } + alert_rule_detectors = AlertRuleDetector.objects.filter( + detector__in=list(open_periods_to_detectors.values()) + ).values_list("alert_rule_id", "detector_id") + detector_ids_to_alert_rule_ids = {} + for alert_rule_id, detector_id in alert_rule_detectors: + detector_ids_to_alert_rule_ids[detector_id] = alert_rule_id + + for open_period in item_list: + detector_id = open_periods_to_detectors[open_period].id + if detector_id in detector_ids_to_alert_rule_ids: + alert_rule_id = detector_ids_to_alert_rule_ids[detector_id] + else: + alert_rule_id = get_fake_id_from_object_id(detector_id) + + results[open_period] = {"projects": [open_period.project.slug]} + results[open_period]["alert_rule"] = alert_rules.get(alert_rule_id) + + if "activities" in self.expand: + gopas = list( + GroupOpenPeriodActivity.objects.filter(group_open_period__in=item_list)[:1000] + ) + open_period_activities = defaultdict(list) + # XXX: the incident endpoint is undocumented, so we aren' on the hook for supporting + # any specific payloads. Since this isn't used on the Sentry side for notification charts, + # I've opted to just use the GroupOpenPeriodActivity serializer. + for gopa, serialized_activity in zip( + gopas, + serialize(gopas, user=user, serializer=GroupOpenPeriodActivitySerializer()), + ): + open_period_activities[gopa.group_open_period_id].append(serialized_activity) + for open_period in item_list: + results[open_period]["activities"] = open_period_activities[open_period.id] + + return results + def get_open_periods_to_detectors( self, open_periods: Sequence[GroupOpenPeriod] ) -> dict[GroupOpenPeriod, Detector]: + # open period -> group -> detector via detectorgroup + groups = [op.group for op in open_periods] + group_to_open_periods = defaultdict(list) + + for op in open_periods: + group_to_open_periods[op.group].append(op) + + detector_groups = DetectorGroup.objects.filter(group__in=groups).select_related( + "group", "detector" + ) + + groups_to_detectors = {} + for dg in detector_groups: + groups_to_detectors[dg.group] = dg.detector + open_periods_to_detectors = {} + for group in group_to_open_periods: + for op in group_to_open_periods[group]: + open_periods_to_detectors[op] = groups_to_detectors[group] return open_periods_to_detectors @@ -44,7 +145,7 @@ def serialize( incident_id = igop.incident_id incident_identifier = igop.incident_identifier except IncidentGroupOpenPeriod.DoesNotExist: - incident_id = get_object_id_from_fake_id(obj.id) + incident_id = get_fake_id_from_object_id(obj.id) incident_identifier = incident_id # TODO: get event time using offset From f9146ced06158f70a3e700a62f41ba254b696743 Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Mon, 10 Nov 2025 16:55:13 -0800 Subject: [PATCH 3/6] fixed some stuff --- .../serializers/workflow_engine_incident.py | 2 +- .../test_workflow_engine_incident.py | 26 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py index e2f124a9a6c2ee..226e54af2b6158 100644 --- a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py +++ b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py @@ -85,7 +85,7 @@ def get_attrs( alert_rule_id = get_fake_id_from_object_id(detector_id) results[open_period] = {"projects": [open_period.project.slug]} - results[open_period]["alert_rule"] = alert_rules.get(alert_rule_id) + results[open_period]["alert_rule"] = alert_rules.get(str(alert_rule_id)) if "activities" in self.expand: gopas = list( diff --git a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py index e0faa80a243052..fb0f018ef2cbe1 100644 --- a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py +++ b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py @@ -1,10 +1,9 @@ from sentry.api.serializers import serialize -from sentry.incidents.endpoints.serializers.alert_rule import DetailedAlertRuleSerializer from sentry.incidents.endpoints.serializers.workflow_engine_incident import ( WorkflowEngineDetailedIncidentSerializer, WorkflowEngineIncidentSerializer, ) -from sentry.incidents.models.incident import Incident +from sentry.incidents.models.incident import IncidentStatus, IncidentStatusMethod, IncidentType from tests.sentry.incidents.serializers.test_workflow_engine_base import ( TestWorkflowEngineSerializer, ) @@ -15,24 +14,23 @@ def setUp(self) -> None: super().setUp() self.add_warning_trigger() self.add_incident_data() - incident = Incident.objects.get(id=self.incident_group_open_period.incident_id) + self.create_detector_group(detector=self.detector, group=self.group_open_period.group) self.incident_identifier = str(self.incident_group_open_period.incident_identifier) - alert_rule_serializer = DetailedAlertRuleSerializer() self.incident_expected = { "id": str(self.incident_group_open_period.incident_id), "identifier": self.incident_identifier, - "organizationId": str(incident.organization_id), + "organizationId": str(self.group_open_period.project.organization_id), "projects": [self.project.slug], - "alertRule": serialize(incident.alert_rule, serializer=alert_rule_serializer), + "alertRule": self.expected, "activities": None, - "status": incident.status, - "statusMethod": incident.status_method, - "type": incident.type, - "title": incident.title, - "dateStarted": incident.date_started, - "dateDetected": incident.date_detected, - "dateCreated": incident.date_added, - "dateClosed": incident.date_closed, + "status": IncidentStatus.CRITICAL.value, + "statusMethod": IncidentStatusMethod.RULE_TRIGGERED.value, + "type": IncidentType.ALERT_TRIGGERED.value, + "title": self.group.title, + "dateStarted": self.group_open_period.date_started, + "dateDetected": self.group_open_period.date_started, + "dateCreated": self.group_open_period.date_added, + "dateClosed": None, } def test_simple(self) -> None: From d329aa1b6fc22165ebb43bced015a1556ae29522 Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Tue, 11 Nov 2025 12:01:58 -0800 Subject: [PATCH 4/6] add detectorgroup to tests --- .../incidents/serializers/test_workflow_engine_base.py | 1 + .../incidents/serializers/test_workflow_engine_incident.py | 6 +++++- .../test_metric_alert_registry_handlers.py | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/sentry/incidents/serializers/test_workflow_engine_base.py b/tests/sentry/incidents/serializers/test_workflow_engine_base.py index 1b4864e6a9d3a3..5e05812b388321 100644 --- a/tests/sentry/incidents/serializers/test_workflow_engine_base.py +++ b/tests/sentry/incidents/serializers/test_workflow_engine_base.py @@ -62,6 +62,7 @@ def setUp(self) -> None: self.alert_rule ) + self.create_detector_group(detector=self.detector, group=self.group) self.expected_critical_action = [ { "id": str(self.critical_trigger_action.id), diff --git a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py index fb0f018ef2cbe1..80fe9c4a2762d2 100644 --- a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py +++ b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py @@ -14,7 +14,6 @@ def setUp(self) -> None: super().setUp() self.add_warning_trigger() self.add_incident_data() - self.create_detector_group(detector=self.detector, group=self.group_open_period.group) self.incident_identifier = str(self.incident_group_open_period.incident_identifier) self.incident_expected = { "id": str(self.incident_group_open_period.incident_id), @@ -45,3 +44,8 @@ def test_detailed(self) -> None: ) self.incident_expected["discoverQuery"] = "(event.type:error) AND (level:error)" assert serialized_incident == self.incident_expected + + def test_no_incident(self) -> None: + """ + Assert that nothing breaks if the IGOP does not exist. + """ diff --git a/tests/sentry/notifications/notification_action/test_metric_alert_registry_handlers.py b/tests/sentry/notifications/notification_action/test_metric_alert_registry_handlers.py index 9712b2b38ef9b5..ef4d8e480f6926 100644 --- a/tests/sentry/notifications/notification_action/test_metric_alert_registry_handlers.py +++ b/tests/sentry/notifications/notification_action/test_metric_alert_registry_handlers.py @@ -138,6 +138,7 @@ def create_models(self): self.group.priority = PriorityLevel.HIGH.value self.group.save() + self.create_detector_group(detector=self.detector, group=self.group) self.open_period, _ = GroupOpenPeriod.objects.get_or_create( group=self.group, project=self.project, From 59eb9291dd5ac764a36c99a65c073c6c4a09b86a Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Tue, 11 Nov 2025 13:50:49 -0800 Subject: [PATCH 5/6] more tests --- .../test_workflow_engine_incident.py | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py index 80fe9c4a2762d2..40d0fcf294bdf0 100644 --- a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py +++ b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py @@ -1,9 +1,17 @@ from sentry.api.serializers import serialize +from sentry.incidents.endpoints.serializers.utils import OFFSET from sentry.incidents.endpoints.serializers.workflow_engine_incident import ( WorkflowEngineDetailedIncidentSerializer, WorkflowEngineIncidentSerializer, ) from sentry.incidents.models.incident import IncidentStatus, IncidentStatusMethod, IncidentType +from sentry.models.groupopenperiodactivity import GroupOpenPeriodActivity, OpenPeriodActivityType +from sentry.types.group import PriorityLevel +from sentry.workflow_engine.models import ( + ActionAlertRuleTriggerAction, + AlertRuleDetector, + DataConditionAlertRuleTrigger, +) from tests.sentry.incidents.serializers.test_workflow_engine_base import ( TestWorkflowEngineSerializer, ) @@ -47,5 +55,66 @@ def test_detailed(self) -> None: def test_no_incident(self) -> None: """ - Assert that nothing breaks if the IGOP does not exist. + Assert that nothing breaks if the legacy models do not exist. """ + self.incident_group_open_period.delete() + ard = AlertRuleDetector.objects.filter(detector_id=self.detector.id) + dcart = DataConditionAlertRuleTrigger.objects.filter( + data_condition_id=self.critical_detector_trigger.id + ) + aarta = ActionAlertRuleTriggerAction.objects.filter(action_id=self.critical_action.id) + + ard.delete() + dcart.delete() + aarta.delete() + + serialized_incident = serialize( + self.group_open_period, self.user, WorkflowEngineIncidentSerializer() + ) + self.expected.update({"id": str(self.detector.id + OFFSET)}) + self.expected["triggers"][0].update( + { + "id": str(self.critical_detector_trigger.id + OFFSET), + "alertRuleId": str(self.detector.id + OFFSET), + } + ) + self.expected["triggers"][1].update( + { + "alertRuleId": str(self.detector.id + OFFSET), + } + ) + self.expected["triggers"][0]["actions"][0].update( + { + "id": str(self.critical_action.id + OFFSET), + "alertRuleTriggerId": str(self.critical_detector_trigger.id + OFFSET), + } + ) + + self.incident_expected.update( + { + "id": str(self.group_open_period.id + OFFSET), + "identifier": str(self.group_open_period.id + OFFSET), + } + ) + assert serialized_incident == self.incident_expected + + def test_with_activities(self) -> None: + gopa = GroupOpenPeriodActivity.objects.create( + date_added=self.group_open_period.date_added, + group_open_period=self.group_open_period, + type=OpenPeriodActivityType.OPENED, + value=self.group.priority, + ) + serialized_incident = serialize( + self.group_open_period, + self.user, + WorkflowEngineIncidentSerializer(expand=["activities"]), + ) + assert len(serialized_incident["activities"]) == 1 + serialized_activity = serialized_incident["activities"][0] + assert serialized_activity == { + "id": str(gopa.id), + "type": OpenPeriodActivityType.OPENED.to_str(), + "value": PriorityLevel(self.group.priority).to_str(), + "dateCreated": gopa.date_added, + } From c9f7f8bd07f40b6bd2aa287b97ba7f8860ea58eb Mon Sep 17 00:00:00 2001 From: Michelle Fu Date: Tue, 11 Nov 2025 16:03:44 -0800 Subject: [PATCH 6/6] variable --- .../serializers/workflow_engine_incident.py | 1 - .../test_workflow_engine_incident.py | 22 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py index 226e54af2b6158..15c99f79e387fc 100644 --- a/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py +++ b/src/sentry/incidents/endpoints/serializers/workflow_engine_incident.py @@ -148,7 +148,6 @@ def serialize( incident_id = get_fake_id_from_object_id(obj.id) incident_identifier = incident_id - # TODO: get event time using offset date_closed = obj.date_ended.replace(second=0, microsecond=0) if obj.date_ended else None return { "id": str(incident_id), diff --git a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py index 40d0fcf294bdf0..2a8e4cda9e7eb6 100644 --- a/tests/sentry/incidents/serializers/test_workflow_engine_incident.py +++ b/tests/sentry/incidents/serializers/test_workflow_engine_incident.py @@ -1,5 +1,5 @@ from sentry.api.serializers import serialize -from sentry.incidents.endpoints.serializers.utils import OFFSET +from sentry.incidents.endpoints.serializers.utils import get_fake_id_from_object_id from sentry.incidents.endpoints.serializers.workflow_engine_incident import ( WorkflowEngineDetailedIncidentSerializer, WorkflowEngineIncidentSerializer, @@ -71,29 +71,33 @@ def test_no_incident(self) -> None: serialized_incident = serialize( self.group_open_period, self.user, WorkflowEngineIncidentSerializer() ) - self.expected.update({"id": str(self.detector.id + OFFSET)}) + fake_alert_rule_id = get_fake_id_from_object_id(self.detector.id) + fake_incident_id = get_fake_id_from_object_id(self.group_open_period.id) + self.expected.update({"id": str(fake_alert_rule_id)}) self.expected["triggers"][0].update( { - "id": str(self.critical_detector_trigger.id + OFFSET), - "alertRuleId": str(self.detector.id + OFFSET), + "id": str(get_fake_id_from_object_id(self.critical_detector_trigger.id)), + "alertRuleId": str(fake_alert_rule_id), } ) self.expected["triggers"][1].update( { - "alertRuleId": str(self.detector.id + OFFSET), + "alertRuleId": str(fake_alert_rule_id), } ) self.expected["triggers"][0]["actions"][0].update( { - "id": str(self.critical_action.id + OFFSET), - "alertRuleTriggerId": str(self.critical_detector_trigger.id + OFFSET), + "id": str(get_fake_id_from_object_id(self.critical_action.id)), + "alertRuleTriggerId": str( + get_fake_id_from_object_id(self.critical_detector_trigger.id) + ), } ) self.incident_expected.update( { - "id": str(self.group_open_period.id + OFFSET), - "identifier": str(self.group_open_period.id + OFFSET), + "id": str(fake_incident_id), + "identifier": str(fake_incident_id), } ) assert serialized_incident == self.incident_expected