Example #1
0
 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])
Example #3
0
 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
Example #4
0
    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
Example #5
0
    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"})
Example #6
0
 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])
Example #8
0
    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])
Example #9
0
 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",
     )
Example #11
0
    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
Example #12
0
 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))
Example #13
0
 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]
Example #14
0
 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
Example #15
0
 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
Example #17
0
 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
Example #18
0
 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)
Example #19
0
    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),
            },
        )
Example #20
0
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])
Example #22
0
    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),
            },
        )
Example #23
0
    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")
Example #24
0
 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])
Example #26
0
 def create(self, validated_data):
     return create_alert_rule_trigger_action(trigger=self.context["trigger"], **validated_data)
Example #27
0
    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])
Example #28
0
 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"])