예제 #1
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)
     title = u"{}: {}".format("Resolved", alert_rule.name)
     assert build_incident_attachment(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":
         "Sentry Incident",
         "ts":
         to_timestamp(incident.date_started),
         "color":
         RESOLVED_COLOR,
         "actions": [],
     }
예제 #2
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)
예제 #3
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
예제 #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)
        integration_key = "pfc73e8cb4s44d519f3d63d45b5q77g9"
        metric_value = 1000
        data = build_incident_attachment(incident, integration_key,
                                         metric_value)

        assert data["routing_key"] == "pfc73e8cb4s44d519f3d63d45b5q77g9"
        assert data["event_action"] == "trigger"
        assert data["dedup_key"] == "incident_{}_{}".format(
            incident.organization_id, incident.identifier)
        assert data["payload"]["summary"] == alert_rule.name
        assert data["payload"]["severity"] == "critical"
        assert data["payload"]["source"] == six.text_type(incident.identifier)
        assert data["payload"]["custom_details"] == {
            "details":
            "1000 events in the last 10 minutes\nFilter: level:error"
        }
        assert data["links"][0]["text"] == "Critical: {}".format(
            alert_rule.name)
        assert data["links"][0][
            "href"] == "http://testserver/organizations/baz/alerts/1/"
예제 #5
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/"
예제 #6
0
    def test_simple(self):
        logo_url = absolute_uri(get_asset_url("sentry", "images/sentry-email-avatar.png"))

        incident = self.create_incident()
        title = "INCIDENT: {} (#{})".format(incident.title, incident.identifier)
        assert build_incident_attachment(incident) == {
            "fallback": title,
            "title": title,
            "title_link": absolute_uri(
                reverse(
                    "sentry-incident",
                    kwargs={
                        "organization_slug": incident.organization.slug,
                        "incident_id": incident.identifier,
                    },
                )
            ),
            "text": " ",
            "fields": [
                {"title": "Status", "value": "Open", "short": True},
                {"title": "Events", "value": 0, "short": True},
                {"title": "Users", "value": 0, "short": True},
            ],
            "mrkdwn_in": ["text"],
            "footer_icon": logo_url,
            "footer": "Sentry Incident",
            "ts": to_timestamp(incident.date_started),
            "color": LEVEL_TO_COLOR["error"],
            "actions": [],
        }
예제 #7
0
 def test_valid_token(self):
     responses.add(responses.POST, 'https://slack.com/api/chat.unfurl',
                   json={'ok': True})
     org2 = self.create_organization(name='biz')
     project1 = self.create_project(organization=self.org)
     project2 = self.create_project(organization=org2)
     group1 = self.create_group(project=project1)
     group2 = self.create_group(project=project2)
     incident = self.create_incident(organization=self.org, projects=[project1])
     incident.update(identifier=123)
     resp = self.post_webhook(event_data=json.loads(LINK_SHARED_EVENT % {
         'group1': group1.id,
         'group2': group2.id,
         'incident': incident.identifier,
         'org1': self.org.slug,
         'org2': org2.slug,
     }))
     assert resp.status_code == 200, resp.content
     data = dict(parse_qsl(responses.calls[0].request.body))
     unfurls = json.loads(data['unfurls'])
     issue_url = 'http://testserver/organizations/%s/issues/%s/bar/' % (
         self.org.slug,
         group1.id,
     )
     incident_url = 'http://testserver/organizations/%s/incidents/%s/' % (
         self.org.slug,
         incident.identifier,
     )
     assert unfurls == {
         issue_url: build_group_attachment(group1),
         incident_url: build_incident_attachment(incident),
     }
예제 #8
0
def unfurl_incidents(request, integration,
                     links: List[UnfurlableUrl]) -> 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
    }
예제 #9
0
    def test_simple(self):
        logo_url = absolute_uri(get_asset_url('sentry', 'images/sentry-email-avatar.png'))

        incident = self.create_incident()
        title = 'INCIDENT: {} (#{})'.format(incident.title, incident.identifier)
        assert build_incident_attachment(incident) == {
            'fallback': title,
            'title': title,
            'title_link': absolute_uri(reverse(
                'sentry-incident',
                kwargs={
                    'organization_slug': incident.organization.slug,
                    'incident_id': incident.identifier,
                },
            )),
            'text': ' ',
            'fields': [
                {'title': 'Status', 'value': 'Open', 'short': True},
                {'title': 'Events', 'value': 0, 'short': True},
                {'title': 'Users', 'value': 0, 'short': True},
            ],
            'mrkdwn_in': ['text'],
            'footer_icon': logo_url,
            'footer': 'Sentry Incident',
            'ts': to_timestamp(incident.date_started),
            'color': LEVEL_TO_COLOR['error'],
            'actions': [],
        }
예제 #10
0
    def test_valid_token(self):
        responses.add(responses.POST,
                      "https://slack.com/api/chat.unfurl",
                      json={"ok": True})
        org2 = self.create_organization(name="biz")
        project1 = self.create_project(organization=self.org)
        project2 = self.create_project(organization=org2)
        min_ago = iso_format(before_now(minutes=1))
        group1 = self.create_group(project=project1)
        group2 = self.create_group(project=project2)
        event = self.store_event(data={
            "fingerprint": ["group3"],
            "timestamp": min_ago
        },
                                 project_id=project1.id)
        group3 = event.group
        alert_rule = self.create_alert_rule()
        incident = self.create_incident(status=2,
                                        organization=self.org,
                                        projects=[project1],
                                        alert_rule=alert_rule)
        incident.update(identifier=123)
        resp = self.post_webhook(event_data=json.loads(
            LINK_SHARED_EVENT % {
                "group1": group1.id,
                "group2": group2.id,
                "group3": group3.id,
                "incident": incident.identifier,
                "org1": self.org.slug,
                "org2": org2.slug,
                "event": event.event_id,
            }))
        assert resp.status_code == 200, resp.content
        data = dict(parse_qsl(responses.calls[0].request.body))
        unfurls = json.loads(data["unfurls"])
        issue_url = "http://testserver/organizations/%s/issues/%s/bar/" % (
            self.org.slug, group1.id)
        incident_url = "http://testserver/organizations/%s/incidents/%s/" % (
            self.org.slug,
            incident.identifier,
        )
        event_url = "http://testserver/organizations/%s/issues/%s/events/%s/" % (
            self.org.slug,
            group3.id,
            event.event_id,
        )

        assert unfurls == {
            issue_url:
            build_group_attachment(group1),
            incident_url:
            build_incident_attachment(incident),
            event_url:
            build_group_attachment(group3, event=event, link_to_event=True),
        }
        assert data["token"] == "xoxp-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"
예제 #11
0
    def run_test(self, incident, method):
        from sentry.integrations.slack.utils 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)
        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(
                action, incident, metric_value, method)
예제 #12
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)
        data = json.loads(responses.calls[1].request.body)

        assert data["attachments"][0]["content"] == build_incident_attachment(
            action, incident, metric_value, method)
예제 #13
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": [],
     }
예제 #14
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":
         RESOLVED_COLOR,
         "actions": [],
     }