Beispiel #1
0
    def run_test(self, incident, method):
        from sentry.integrations.pagerduty.utils import build_incident_attachment

        action = self.create_alert_rule_trigger_action(
            target_identifier=self.service.id,
            type=AlertRuleTriggerAction.Type.PAGERDUTY,
            target_type=AlertRuleTriggerAction.TargetType.SPECIFIC,
            integration=self.integration,
        )

        responses.add(
            method=responses.POST,
            url="https://events.pagerduty.com/v2/enqueue/",
            json={},
            status=202,
            content_type="application/json",
        )
        handler = PagerDutyActionHandler(action, incident, self.project)
        metric_value = 1000
        with self.tasks():
            getattr(handler, method)(metric_value)
        data = responses.calls[0].request.body

        assert json.loads(data) == build_incident_attachment(
            action, incident, self.service.integration_key, metric_value,
            method)
Beispiel #2
0
    def run_test(self, incident, method):
        from sentry.rules.actions.notify_event_service import build_incident_attachment

        action = self.create_alert_rule_trigger_action(
            target_identifier=self.sentry_app.id,
            type=AlertRuleTriggerAction.Type.SENTRY_APP,
            target_type=AlertRuleTriggerAction.TargetType.SENTRY_APP,
            sentry_app=self.sentry_app,
        )

        responses.add(
            method=responses.POST,
            url="https://example.com/webhook",
            status=200,
            content_type="application/json",
            body=json.dumps({"ok": "true"}),
        )

        handler = SentryAppActionHandler(action, incident, self.project)
        metric_value = 1000
        with self.tasks():
            getattr(handler, method)(metric_value)
        data = responses.calls[0].request.body
        assert json.dumps(
            build_incident_attachment(action, incident, metric_value,
                                      method)) in data
Beispiel #3
0
def send_incident_alert_notification(action, incident, metric_value, method):
    from sentry.integrations.slack.message_builder.incidents import build_incident_attachment

    # Make sure organization integration is still active:
    try:
        integration = Integration.objects.get(
            id=action.integration_id,
            organizations=incident.organization,
            status=ObjectStatus.VISIBLE,
        )
    except Integration.DoesNotExist:
        # Integration removed, but rule is still active.
        return

    channel = action.target_identifier
    attachment = build_incident_attachment(action, incident, metric_value, method)
    payload = {
        "token": integration.metadata["access_token"],
        "channel": channel,
        "attachments": json.dumps([attachment]),
    }

    client = SlackClient()
    try:
        client.post("/chat.postMessage", data=payload, timeout=5)
    except ApiError as e:
        logger.info("rule.fail.slack_post", extra={"error": str(e)})
Beispiel #4
0
    def test_build_incident_attachment(self):
        from sentry.integrations.pagerduty.utils import build_incident_attachment

        alert_rule = self.create_alert_rule()
        incident = self.create_incident(alert_rule=alert_rule)
        update_incident_status(
            incident,
            IncidentStatus.CRITICAL,
            status_method=IncidentStatusMethod.RULE_TRIGGERED)
        action = self.create_alert_rule_trigger_action(
            target_identifier=self.service.id,
            type=AlertRuleTriggerAction.Type.PAGERDUTY,
            target_type=AlertRuleTriggerAction.TargetType.SPECIFIC,
            integration=self.integration,
        )
        metric_value = 1000
        data = build_incident_attachment(action, incident,
                                         self.integration_key, metric_value)

        assert data["routing_key"] == self.integration_key
        assert data["event_action"] == "trigger"
        assert data[
            "dedup_key"] == f"incident_{incident.organization_id}_{incident.identifier}"
        assert data["payload"]["summary"] == alert_rule.name
        assert data["payload"]["severity"] == "critical"
        assert data["payload"]["source"] == str(incident.identifier)
        assert data["payload"]["custom_details"] == {
            "details":
            "1000 events in the last 10 minutes\nFilter: level:error"
        }
        assert data["links"][0]["text"] == f"Critical: {alert_rule.name}"
        assert data["links"][0][
            "href"] == "http://testserver/organizations/baz/alerts/1/"
Beispiel #5
0
    def test_unfurl_incidents(self):
        alert_rule = self.create_alert_rule()

        incident = self.create_incident(status=2,
                                        organization=self.organization,
                                        projects=[self.project],
                                        alert_rule=alert_rule)
        incident.update(identifier=123)
        trigger = self.create_alert_rule_trigger(alert_rule,
                                                 CRITICAL_TRIGGER_LABEL, 100)
        action = self.create_alert_rule_trigger_action(
            alert_rule_trigger=trigger, triggered_for_incident=incident)

        links = [
            UnfurlableUrl(
                url=
                f"https://sentry.io/organizations/{self.organization.slug}/alerts/rules/details/{incident.identifier}/",
                args={
                    "org_slug": self.organization.slug,
                    "incident_id": incident.identifier
                },
            ),
        ]
        unfurls = link_handlers[LinkType.INCIDENTS].fn(self.request,
                                                       self.integration, links)

        assert unfurls[links[0].url] == build_incident_attachment(
            action, incident)
Beispiel #6
0
def unfurl_incidents(
    request: HttpRequest,
    integration: Integration,
    links: List[UnfurlableUrl],
    user: Optional["User"] = None,
) -> UnfurledUrl:
    filter_query = Q()
    # Since we don't have real ids here, we use the org slug so that we can
    # make sure the identifiers correspond to the correct organization.
    for link in links:
        identifier = link.args["incident_id"]
        org_slug = link.args["org_slug"]
        filter_query |= Q(identifier=identifier, organization__slug=org_slug)

    results = {
        i.identifier: i
        for i in Incident.objects.filter(
            filter_query,
            # Filter by integration organization here as well to make sure that
            # we have permission to access these incidents.
            organization__in=integration.organizations.all(),
        )
    }
    if not results:
        return {}

    return {
        link.url: build_incident_attachment(
            action=None,
            incident=results[link.args["incident_id"]],
        )
        for link in links if link.args["incident_id"] in results
    }
Beispiel #7
0
    def run_test(self, incident, method):
        from sentry.integrations.slack.message_builder.incidents import build_incident_attachment

        token = "xoxb-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"
        integration = Integration.objects.create(
            external_id="1",
            provider="slack",
            metadata={
                "access_token": token,
                "installation_type": "born_as_bot"
            },
        )
        integration.add_organization(self.organization, self.user)
        channel_id = "some_id"
        channel_name = "#hello"
        responses.add(
            method=responses.GET,
            url="https://slack.com/api/conversations.list",
            status=200,
            content_type="application/json",
            body=json.dumps({
                "ok":
                "true",
                "channels": [{
                    "name": channel_name[1:],
                    "id": channel_id
                }]
            }),
        )

        action = self.create_alert_rule_trigger_action(
            target_identifier=channel_name,
            type=AlertRuleTriggerAction.Type.SLACK,
            target_type=AlertRuleTriggerAction.TargetType.SPECIFIC,
            integration=integration,
        )
        responses.add(
            method=responses.POST,
            url="https://slack.com/api/chat.postMessage",
            status=200,
            content_type="application/json",
            body='{"ok": true}',
        )
        handler = SlackActionHandler(action, incident, self.project)
        metric_value = 1000
        with self.tasks():
            getattr(handler, method)(metric_value,
                                     IncidentStatus(incident.status))
        data = parse_qs(responses.calls[1].request.body)
        assert data["channel"] == [channel_id]
        assert data["token"] == [token]
        assert json.loads(
            data["attachments"][0])[0] == build_incident_attachment(
                incident, metric_value)
Beispiel #8
0
    def run_test(self, incident, method):
        from sentry.integrations.msteams.card_builder import build_incident_attachment

        integration = Integration.objects.create(
            provider="msteams",
            name="Galactic Empire",
            external_id="D4r7h_Pl4gu315_th3_w153",
            metadata={
                "service_url": "https://smba.trafficmanager.net/amer",
                "access_token": "d4rk51d3",
                "expires_at": int(time.time()) + 86400,
            },
        )
        integration.add_organization(self.organization, self.user)

        channel_id = "d_s"
        channel_name = "Death Star"
        channels = [{"id": channel_id, "name": channel_name}]

        responses.add(
            method=responses.GET,
            url=
            "https://smba.trafficmanager.net/amer/v3/teams/D4r7h_Pl4gu315_th3_w153/conversations",
            json={"conversations": channels},
        )

        action = self.create_alert_rule_trigger_action(
            target_identifier=channel_name,
            type=AlertRuleTriggerAction.Type.MSTEAMS,
            target_type=AlertRuleTriggerAction.TargetType.SPECIFIC,
            integration=integration,
        )

        responses.add(
            method=responses.POST,
            url=
            "https://smba.trafficmanager.net/amer/v3/conversations/d_s/activities",
            status=200,
            json={},
        )

        handler = MsTeamsActionHandler(action, incident, self.project)
        metric_value = 1000
        with self.tasks():
            getattr(handler, method)(metric_value,
                                     IncidentStatus(incident.status))
        data = json.loads(responses.calls[1].request.body)

        assert data["attachments"][0]["content"] == build_incident_attachment(
            incident, IncidentStatus(incident.status), metric_value)
Beispiel #9
0
 def test_metric_value(self):
     logo_url = absolute_uri(
         get_asset_url("sentry", "images/sentry-email-avatar.png"))
     alert_rule = self.create_alert_rule()
     incident = self.create_incident(alert_rule=alert_rule, status=2)
     title = f"Critical: {alert_rule.name}"  # This test will use the action/method and not the incident to build status
     metric_value = 5000
     trigger = self.create_alert_rule_trigger(alert_rule,
                                              CRITICAL_TRIGGER_LABEL, 100)
     action = self.create_alert_rule_trigger_action(
         alert_rule_trigger=trigger, triggered_for_incident=incident)
     incident_footer_ts = (
         "<!date^{:.0f}^Sentry Incident - Started {} at {} | Sentry Incident>"
         .format(to_timestamp(incident.date_started), "{date_pretty}",
                 "{time}"))
     # This should fail because it pulls status from `action` instead of `incident`
     assert build_incident_attachment(
         action, incident, metric_value=metric_value, method="fire"
     ) == {
         "fallback":
         title,
         "title":
         title,
         "title_link":
         absolute_uri(
             reverse(
                 "sentry-metric-alert",
                 kwargs={
                     "organization_slug": incident.organization.slug,
                     "incident_id": incident.identifier,
                 },
             )),
         "text":
         f"{metric_value} events in the last 10 minutes\nFilter: level:error",
         "fields": [],
         "mrkdwn_in": ["text"],
         "footer_icon":
         logo_url,
         "footer":
         incident_footer_ts,
         "color":
         LEVEL_TO_COLOR["fatal"],
         "actions": [],
     }
Beispiel #10
0
    def run_test(self, incident, method):
        from sentry.rules.actions.notify_event_service import build_incident_attachment

        trigger = self.create_alert_rule_trigger(self.alert_rule, "hi", 1000)
        action = self.create_alert_rule_trigger_action(
            alert_rule_trigger=trigger,
            target_identifier=self.sentry_app.id,
            type=AlertRuleTriggerAction.Type.SENTRY_APP,
            target_type=AlertRuleTriggerAction.TargetType.SENTRY_APP,
            sentry_app=self.sentry_app,
            sentry_app_config={
                "channel": "#santry",
                "workspace": "santrysantrysantry",
                "tag": "triage",
                "assignee": "Nisanthan Nanthakumar",
            },
        )

        responses.add(
            method=responses.POST,
            url="https://example.com/webhook",
            status=200,
            content_type="application/json",
            body=json.dumps({"ok": "true"}),
        )

        handler = SentryAppActionHandler(action, incident, self.project)
        metric_value = 1000
        with self.tasks():
            getattr(handler, method)(metric_value)
        data = responses.calls[0].request.body
        assert json.dumps(
            build_incident_attachment(action, incident, metric_value,
                                      method)) in data
        # Check that the Alert Rule UI Component settings are returned
        assert json.loads(data)["data"]["metric_alert"]["alert_rule"][
            "triggers"][0]["actions"][0]["settings"] == {
                "channel": "#santry",
                "workspace": "santrysantrysantry",
                "tag": "triage",
                "assignee": "Nisanthan Nanthakumar",
            }
Beispiel #11
0
 def test_simple(self):
     logo_url = absolute_uri(
         get_asset_url("sentry", "images/sentry-email-avatar.png"))
     alert_rule = self.create_alert_rule()
     incident = self.create_incident(alert_rule=alert_rule, status=2)
     trigger = self.create_alert_rule_trigger(alert_rule,
                                              CRITICAL_TRIGGER_LABEL, 100)
     action = self.create_alert_rule_trigger_action(
         alert_rule_trigger=trigger, triggered_for_incident=incident)
     title = f"Resolved: {alert_rule.name}"
     incident_footer_ts = (
         "<!date^{:.0f}^Sentry Incident - Started {} at {} | Sentry Incident>"
         .format(to_timestamp(incident.date_started), "{date_pretty}",
                 "{time}"))
     assert build_incident_attachment(action, incident) == {
         "fallback":
         title,
         "title":
         title,
         "title_link":
         absolute_uri(
             reverse(
                 "sentry-metric-alert",
                 kwargs={
                     "organization_slug": incident.organization.slug,
                     "incident_id": incident.identifier,
                 },
             )),
         "text":
         "0 events in the last 10 minutes\nFilter: level:error",
         "fields": [],
         "mrkdwn_in": ["text"],
         "footer_icon":
         logo_url,
         "footer":
         incident_footer_ts,
         "color":
         INCIDENT_RESOLVED_COLOR,
         "actions": [],
     }