def rule(self): rule = create_alert_rule( self.organization, [self.project, self.other_project], "some rule", AlertRuleThresholdType.ABOVE, query="", aggregation=QueryAggregations.TOTAL, time_window=1, alert_threshold=100, resolve_threshold=10, threshold_period=1, ) # Make sure the trigger exists trigger = create_alert_rule_trigger(rule, "hi", AlertRuleThresholdType.ABOVE, 100, resolve_threshold=10) create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, six.text_type(self.user.id), ) return rule
def test_alert_dedupe(self): # Verify that an alert rule that only expects a single update to be over the # alert threshold triggers correctly rule = self.rule c_trigger = self.trigger c_action_2 = create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, str(self.user.id), ) w_trigger = create_alert_rule_trigger( self.rule, WARNING_TRIGGER_LABEL, c_trigger.alert_threshold - 10 ) create_alert_rule_trigger_action( w_trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, str(self.user.id), ) processor = self.send_update(rule, c_trigger.alert_threshold + 1) self.assert_trigger_counts(processor, self.trigger, 0, 0) incident = self.assert_active_incident(rule) assert incident.date_started == ( timezone.now().replace(microsecond=0) - timedelta(seconds=rule.snuba_query.time_window) ) self.assert_trigger_exists_with_status(incident, self.trigger, TriggerStatus.ACTIVE) self.assert_actions_fired_for_incident(incident, [c_action_2])
def rule(self): with self.tasks(): rule = self.create_alert_rule( name="some rule", query="", aggregate="count()", time_window=1, threshold_period=1 ) trigger = create_alert_rule_trigger( rule, "hi", AlertRuleThresholdType.ABOVE, 100, resolve_threshold=10 ) create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, six.text_type(self.user.id), ) return rule
def test_slack(self): integration = Integration.objects.create( external_id="1", provider="slack", metadata={"access_token": "xoxp-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"}, ) integration.add_organization(self.organization, self.user) type = AlertRuleTriggerAction.Type.SLACK target_type = AlertRuleTriggerAction.TargetType.SPECIFIC channel_name = "#some_channel" channel_id = "s_c" responses.add( method=responses.GET, url="https://slack.com/api/channels.list", status=200, content_type="application/json", body=json.dumps( {"ok": "true", "channels": [{"name": channel_name[1:], "id": channel_id}]} ), ) action = create_alert_rule_trigger_action( self.trigger, type, target_type, target_identifier=channel_name, integration=integration ) assert action.alert_rule_trigger == self.trigger assert action.type == type.value assert action.target_type == target_type.value assert action.target_identifier == channel_id assert action.target_display == channel_name assert action.integration == integration
def test_remove_unchanged_fields(self): type = AlertRuleTriggerAction.Type.EMAIL target_type = AlertRuleTriggerAction.TargetType.SPECIFIC identifier = "hello" action = create_alert_rule_trigger_action(self.trigger, type, target_type, identifier) self._run_changed_fields_test( action, { "type": type.value, "target_type": target_type.value, "target_identifier": identifier }, {}, ) self._run_changed_fields_test(action, {"type": type.value}, {}) self._run_changed_fields_test( action, {"type": AlertRuleTriggerAction.Type.SLACK.value}, {"type": AlertRuleTriggerAction.Type.SLACK}, ) self._run_changed_fields_test(action, {"target_type": target_type.value}, {}) self._run_changed_fields_test( action, {"target_type": AlertRuleTriggerAction.TargetType.USER.value}, {"target_type": AlertRuleTriggerAction.TargetType.USER}, ) self._run_changed_fields_test(action, {"target_identifier": identifier}, {}) self._run_changed_fields_test(action, {"target_identifier": "bye"}, {"target_identifier": "bye"})
def create(self, validated_data): try: return create_alert_rule_trigger_action( trigger=self.context["trigger"], **validated_data ) except InvalidTriggerActionError as e: raise serializers.ValidationError(e.message)
def test_auto_resolve_multiple_trigger(self): # Test auto resolving works correctly when multiple triggers are present. rule = self.rule rule.update(resolve_threshold=None) trigger = self.trigger other_trigger = create_alert_rule_trigger(self.rule, "hello", trigger.alert_threshold - 10) other_action = create_alert_rule_trigger_action( other_trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER) processor = self.send_update(rule, trigger.alert_threshold + 1, timedelta(minutes=-2)) self.assert_trigger_counts(processor, self.trigger, 0, 0) incident = self.assert_active_incident(rule) self.assert_trigger_exists_with_status(incident, self.trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_actions_fired_for_incident(incident, [self.action, other_action]) processor = self.send_update(rule, other_trigger.alert_threshold - 1, timedelta(minutes=-1)) self.assert_trigger_counts(processor, self.trigger, 0, 0) self.assert_no_active_incident(rule) self.assert_trigger_exists_with_status(incident, self.trigger, TriggerStatus.RESOLVED) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_actions_resolved_for_incident(incident, [self.action, other_action])
def test_multiple_triggers_one_with_no_resolve(self): # Check that both triggers fire if an update comes through that exceeds both of # their thresholds rule = self.rule trigger = self.trigger other_trigger = create_alert_rule_trigger( self.rule, "hello", AlertRuleThresholdType.ABOVE, 200 ) other_action = create_alert_rule_trigger_action( other_trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER ) processor = self.send_update( rule, other_trigger.alert_threshold + 1, timedelta(minutes=-10), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_actions_fired_for_incident(incident, [self.action, other_action]) processor = self.send_update( rule, trigger.resolve_threshold - 1, timedelta(minutes=-9), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) self.assert_no_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.RESOLVED) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_actions_resolved_for_incident(incident, [self.action])
def action(self): return create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, target_identifier=six.text_type(self.user.id), )
def action(self): return create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.SPECIFIC, "hello", )
def update(self, instance, validated_data): with transaction.atomic(): validated_data = self._remove_unchanged_fields( instance, validated_data) triggers_data = validated_data.pop("triggers") alert_rule = update_alert_rule(instance, **validated_data) # Delete triggers we don't have present in the updated data. trigger_ids = [x["id"] for x in triggers_data] AlertRuleTrigger.objects.filter(alert_rule=alert_rule).exclude( id__in=trigger_ids).delete() for trigger_data in triggers_data: actions_data = trigger_data.pop("actions") try: if "id" in trigger_data: trigger_instance = AlertRuleTrigger.objects.get( alert_rule=alert_rule, id=trigger_data["id"]) trigger_data.pop("id") trigger = update_alert_rule_trigger( trigger_instance, **trigger_data) else: trigger = create_alert_rule_trigger( alert_rule=alert_rule, **trigger_data) except AlertRuleTriggerLabelAlreadyUsedError: raise serializers.ValidationError( "This trigger label is already in use for this alert rule" ) # Delete actions we don't have present in the updated data. action_ids = [x["id"] for x in actions_data] AlertRuleTriggerAction.objects.filter( alert_rule_trigger=trigger).exclude( id__in=action_ids).delete() for action_data in actions_data: if "id" in action_data: action_instance = AlertRuleTriggerAction.objects.get( alert_rule_trigger=trigger, id=action_data["id"]) action_data.pop("id") update_alert_rule_trigger_action( action_instance, **action_data) else: create_alert_rule_trigger_action(trigger=trigger, **action_data) return alert_rule
def create(self, validated_data): try: return create_alert_rule_trigger_action( trigger=self.context["trigger"], **validated_data ) except InvalidTriggerActionError as e: raise serializers.ValidationError(force_text(e)) except ApiRateLimitedError as e: raise serializers.ValidationError(force_text(e))
def test(self): assert list(get_actions_for_trigger(self.trigger)) == [] action = create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, target_identifier=six.text_type(self.user.id), ) assert list(get_actions_for_trigger(self.trigger)) == [action]
def rule(self): with self.tasks(): rule = self.create_alert_rule( name="some rule", query="", aggregate="count()", time_window=1, threshold_period=1, resolve_threshold=10, ) trigger = create_alert_rule_trigger(rule, CRITICAL_TRIGGER_LABEL, 100) create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, str(self.user.id), ) return rule
def create_alert_rule_trigger_action( trigger, type=AlertRuleTriggerAction.Type.EMAIL, target_type=AlertRuleTriggerAction.TargetType.USER, target_identifier=None, integration=None, ): return create_alert_rule_trigger_action(trigger, type, target_type, target_identifier, integration)
def rule(self): rule = self.create_alert_rule( projects=[self.project, self.other_project], name="some rule", query="", aggregate="count()", time_window=1, threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, ) # Make sure the trigger exists trigger = create_alert_rule_trigger(rule, CRITICAL_TRIGGER_LABEL, 100) create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER, str(self.user.id), ) return rule
def test(self): type = AlertRuleTriggerAction.Type.EMAIL target_type = AlertRuleTriggerAction.TargetType.USER target_identifier = six.text_type(self.user.id) action = create_alert_rule_trigger_action( self.trigger, type, target_type, target_identifier=target_identifier ) assert action.alert_rule_trigger == self.trigger assert action.type == type.value assert action.target_type == target_type.value assert action.target_identifier == target_identifier
def test_simple(self): alert_rule = self.create_alert_rule() trigger = create_alert_rule_trigger(alert_rule, "hi", 1000) action = create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.SPECIFIC, "hello", ) result = serialize(action) self.assert_action_serialized(action, result)
def test_remove_unchanged_fields(self): type = AlertRuleTriggerAction.Type.EMAIL target_type = AlertRuleTriggerAction.TargetType.USER identifier = six.text_type(self.user.id) action = create_alert_rule_trigger_action(self.trigger, type, target_type, identifier) self._run_changed_fields_test( action, { "type": AlertRuleTriggerAction.get_registered_type(type).slug, "target_type": action_target_type_to_string[target_type], "target_identifier": identifier, }, {}, ) integration = Integration.objects.create(external_id="1", provider="slack", metadata={}) self._run_changed_fields_test( action, { "type": AlertRuleTriggerAction.get_registered_type( AlertRuleTriggerAction.Type.SLACK ).slug, "targetIdentifier": identifier, "targetType": action_target_type_to_string[ AlertRuleTriggerAction.TargetType.SPECIFIC ], "integration": integration.id, }, { "type": AlertRuleTriggerAction.Type.SLACK, "integration": integration, "target_identifier": identifier, "target_type": AlertRuleTriggerAction.TargetType.SPECIFIC, }, ) new_team = self.create_team(self.organization) self._run_changed_fields_test( action, { "type": AlertRuleTriggerAction.get_registered_type(type).slug, "target_type": action_target_type_to_string[AlertRuleTriggerAction.TargetType.TEAM], "target_identifier": six.text_type(new_team.id), }, { "type": type, "target_type": AlertRuleTriggerAction.TargetType.TEAM, "target_identifier": six.text_type(new_team.id), }, )
def generate_metric_alert(project): org = project.organization team = Team.objects.filter(organization=org).first() alert_rule = create_alert_rule( org, [project], "High Error Rate", "level:error", "count()", 10, AlertRuleThresholdType.ABOVE, 1, ) critical_trigger = create_alert_rule_trigger(alert_rule, "critical", 10) warning_trigger = create_alert_rule_trigger(alert_rule, "warning", 7) for trigger in [critical_trigger, warning_trigger]: create_alert_rule_trigger_action( trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.TEAM, target_identifier=str(team.id), )
def test_simple(self): self.create_team(organization=self.organization, members=[self.user]) action = create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.SPECIFIC, "hello", ) self.login_as(self.user) with self.feature("organizations:incidents"): resp = self.get_valid_response(self.organization.slug, self.alert_rule.id, self.trigger.id) assert resp.data == serialize([action])
def test_remove_unchanged_fields(self): type = AlertRuleTriggerAction.Type.EMAIL target_type = AlertRuleTriggerAction.TargetType.SPECIFIC identifier = "hello" action = create_alert_rule_trigger_action(self.trigger, type, target_type, identifier) self._run_changed_fields_test( action, { "type": type.value, "target_type": target_type.value, "target_identifier": identifier }, {}, ) self._run_changed_fields_test(action, {"type": type.value}, {}) integration = Integration.objects.create(external_id="1", provider="slack", metadata={}) self._run_changed_fields_test( action, { "type": AlertRuleTriggerAction.Type.SLACK.value, "targetIdentifier": "hello", "targetType": AlertRuleTriggerAction.TargetType.SPECIFIC.value, "integration": integration.id, }, { "type": AlertRuleTriggerAction.Type.SLACK, "integration": integration }, ) self._run_changed_fields_test(action, { "target_type": target_type.value, "target_identifier": identifier }, {}) self._run_changed_fields_test( action, { "target_type": AlertRuleTriggerAction.TargetType.USER.value, "target_identifier": six.text_type(self.user.id), }, { "target_type": AlertRuleTriggerAction.TargetType.USER, "target_identifier": six.text_type(self.user.id), }, )
def create(self, validated_data): with transaction.atomic(): try: # TODO: Remove this, just temporary while we're supporting both fields. if "aggregation" not in validated_data: raise serializers.ValidationError( "aggregation is required") triggers_data = validated_data.pop("triggers") # TODO: User super.create and don't duplicate the aggreagation + duplicate name check? alert_rule = create_alert_rule( organization=self.context["organization"], **validated_data) for trigger_data in triggers_data: trigger_actions_data = trigger_data.pop("actions") trigger = create_alert_rule_trigger(alert_rule=alert_rule, **trigger_data) for actions_data in trigger_actions_data: create_alert_rule_trigger_action(trigger=trigger, **actions_data) return alert_rule except AlertRuleNameAlreadyUsedError: raise serializers.ValidationError( "This name is already in use for this project")
def create(self, validated_data): try: action = create_alert_rule_trigger_action( trigger=self.context["trigger"], **validated_data) except InvalidTriggerActionError as e: raise serializers.ValidationError(force_text(e)) except ApiRateLimitedError as e: raise serializers.ValidationError(force_text(e)) else: analytics.record( "metric_alert_with_ui_component.created", user_id=getattr(self.context["user"], "id", None), alert_rule_id=getattr(self.context["alert_rule"], "id"), organization_id=getattr(self.context["organization"], "id"), ) return action
def test_multiple_triggers_resolve_separately(self): # Check that resolve triggers fire separately rule = self.rule trigger = self.trigger other_trigger = create_alert_rule_trigger(self.rule, "hello", 200) other_action = create_alert_rule_trigger_action( other_trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER ) processor = self.send_update( rule, other_trigger.alert_threshold + 1, timedelta(minutes=-10), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_actions_fired_for_incident(incident, [self.action, other_action]) processor = self.send_update( rule, other_trigger.alert_threshold - 1, timedelta(minutes=-9), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_actions_resolved_for_incident(incident, [other_action]) processor = self.send_update( rule, rule.resolve_threshold - 1, timedelta(minutes=-8), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) self.assert_no_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.RESOLVED) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_actions_resolved_for_incident(incident, [self.action])
def create(self, validated_data): return create_alert_rule_trigger_action(trigger=self.context["trigger"], **validated_data)
def test_multiple_triggers(self): rule = self.rule rule.update(threshold_period=2) trigger = self.trigger other_trigger = create_alert_rule_trigger( self.rule, "hello", AlertRuleThresholdType.ABOVE, 200, resolve_threshold=50 ) other_action = create_alert_rule_trigger_action( other_trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER ) processor = self.send_update( rule, trigger.alert_threshold + 1, timedelta(minutes=-10), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 1, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) self.assert_no_active_incident(rule, self.sub) self.assert_trigger_does_not_exist(trigger) self.assert_trigger_does_not_exist(other_trigger) self.assert_action_handler_called_with_actions(None, []) # This should cause both to increment, although only `trigger` should fire. processor = self.send_update( rule, other_trigger.alert_threshold + 1, timedelta(minutes=-9), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 1, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_does_not_exist(other_trigger) self.assert_actions_fired_for_incident(incident, [self.action]) # Now only `other_trigger` should increment and fire. processor = self.send_update( rule, other_trigger.alert_threshold + 1, timedelta(minutes=-8), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_actions_fired_for_incident(incident, [other_action]) # Now send through two updates where we're below threshold for `other_trigger`. # The trigger should end up resolved, but the incident should still be active processor = self.send_update( rule, other_trigger.resolve_threshold - 1, timedelta(minutes=-7), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 1) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.ACTIVE) self.assert_action_handler_called_with_actions(incident, []) processor = self.send_update( rule, other_trigger.resolve_threshold - 1, timedelta(minutes=-6), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_actions_resolved_for_incident(incident, [other_action]) # Now we push the other trigger below the resolve threshold twice. This should # close the incident. processor = self.send_update( rule, trigger.resolve_threshold - 1, timedelta(minutes=-5), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 1) self.assert_trigger_counts(processor, other_trigger, 0, 0) incident = self.assert_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.ACTIVE) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_action_handler_called_with_actions(incident, []) processor = self.send_update( rule, trigger.resolve_threshold - 1, timedelta(minutes=-4), subscription=self.sub ) self.assert_trigger_counts(processor, trigger, 0, 0) self.assert_trigger_counts(processor, other_trigger, 0, 0) self.assert_no_active_incident(rule, self.sub) self.assert_trigger_exists_with_status(incident, trigger, TriggerStatus.RESOLVED) self.assert_trigger_exists_with_status(incident, other_trigger, TriggerStatus.RESOLVED) self.assert_actions_resolved_for_incident(incident, [self.action])
def action(self): return create_alert_rule_trigger_action( self.trigger, AlertRuleTriggerAction.Type.EMAIL, AlertRuleTriggerAction.TargetType.USER )
def test_slack_multiple_triggers_critical_fired_twice_before_warning(self): """ Test that ensures that when we get a critical update is sent followed by a warning update, the warning update is not swallowed and an alert is triggered as a warning alert granted the count is above the warning trigger threshold """ from sentry.incidents.action_handlers import SlackActionHandler slack_handler = SlackActionHandler # Create Slack Integration integration = Integration.objects.create( provider="slack", name="Team A", external_id="TXXXXXXX1", metadata={ "access_token": "xoxp-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx", "installation_type": "born_as_bot", }, ) integration.add_organization(self.project.organization, self.user) # Register Slack Handler AlertRuleTriggerAction.register_type( "slack", AlertRuleTriggerAction.Type.SLACK, [AlertRuleTriggerAction.TargetType.SPECIFIC], integration_provider="slack", )(slack_handler) rule = self.create_alert_rule( projects=[self.project, self.other_project], name="some rule 2", query="", aggregate="count()", time_window=1, threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, ) trigger = create_alert_rule_trigger(rule, "critical", 100) trigger_warning = create_alert_rule_trigger(rule, "warning", 10) for t in [trigger, trigger_warning]: create_alert_rule_trigger_action( t, AlertRuleTriggerAction.Type.SLACK, AlertRuleTriggerAction.TargetType.SPECIFIC, integration=integration, input_channel_id="#workflow", ) self.assert_slack_calls([]) # Send update above critical self.send_update( rule, trigger.alert_threshold + 5, timedelta(minutes=-10), subscription=rule.snuba_query.subscriptions.filter(project=self.project).get(), ) self.assert_slack_calls(["Critical"]) # Send second update above critical self.send_update( rule, trigger.alert_threshold + 6, timedelta(minutes=-9), subscription=rule.snuba_query.subscriptions.filter(project=self.project).get(), ) self.assert_slack_calls([]) # Send update below critical but above warning self.send_update( rule, trigger_warning.alert_threshold + 5, timedelta(minutes=0), subscription=rule.snuba_query.subscriptions.filter(project=self.project).get(), ) self.assert_active_incident(rule) self.assert_slack_calls(["Warning"])