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)
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
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)})
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/"
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)
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 }
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)
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)
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": [], }
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", }
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": [], }