mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
315 lines
13 KiB
Python
315 lines
13 KiB
Python
import uuid
|
|
from datetime import timedelta
|
|
|
|
import pytest
|
|
from django.utils import timezone
|
|
|
|
from sentry.incidents.logic import CRITICAL_TRIGGER_LABEL
|
|
from sentry.incidents.models import IncidentStatus, IncidentTrigger
|
|
from sentry.integrations.metric_alerts import incident_attachment_info
|
|
from sentry.snuba.dataset import Dataset
|
|
from sentry.testutils.cases import BaseIncidentsTest, BaseMetricsTestCase, SnubaTestCase, TestCase
|
|
from sentry.testutils.helpers.datetime import freeze_time
|
|
from sentry.utils.dates import to_timestamp
|
|
|
|
pytestmark = pytest.mark.sentry_metrics
|
|
|
|
|
|
class IncidentAttachmentInfoTest(TestCase, BaseIncidentsTest):
|
|
def test_returns_correct_info(self):
|
|
alert_rule = self.create_alert_rule()
|
|
date_started = self.now
|
|
incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #1",
|
|
projects=[self.project],
|
|
alert_rule=alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=date_started,
|
|
)
|
|
trigger = self.create_alert_rule_trigger(alert_rule, CRITICAL_TRIGGER_LABEL, 100)
|
|
self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=incident
|
|
)
|
|
metric_value = 123
|
|
referrer = "metric_alert_custom"
|
|
notification_uuid = str(uuid.uuid4())
|
|
data = incident_attachment_info(
|
|
incident,
|
|
IncidentStatus.CLOSED,
|
|
metric_value,
|
|
notification_uuid=notification_uuid,
|
|
referrer=referrer,
|
|
)
|
|
|
|
assert data["title"] == f"Resolved: {alert_rule.name}"
|
|
assert data["status"] == "Resolved"
|
|
assert data["text"] == "123 events in the last 10 minutes"
|
|
assert data["ts"] == date_started
|
|
assert (
|
|
data["title_link"]
|
|
== f"http://testserver/organizations/baz/alerts/rules/details/{alert_rule.id}/?alert={incident.identifier}&referrer={referrer}¬ification_uuid={notification_uuid}"
|
|
)
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_with_incident_trigger(self):
|
|
alert_rule = self.create_alert_rule()
|
|
now = self.now
|
|
date_started = now - timedelta(minutes=5)
|
|
event_date = now - timedelta(minutes=5)
|
|
|
|
self.create_event(event_date)
|
|
self.create_event(event_date)
|
|
self.create_event(event_date)
|
|
self.create_event(event_date)
|
|
|
|
incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #2",
|
|
projects=[self.project],
|
|
alert_rule=alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=date_started,
|
|
query="",
|
|
)
|
|
trigger = self.create_alert_rule_trigger(alert_rule, CRITICAL_TRIGGER_LABEL, 100)
|
|
self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=incident
|
|
)
|
|
|
|
incident_trigger = (
|
|
IncidentTrigger.objects.filter(incident=incident).order_by("-date_modified").first()
|
|
)
|
|
incident_trigger.update(date_modified=now)
|
|
|
|
# Test the trigger "firing"
|
|
data = incident_attachment_info(incident, IncidentStatus.CRITICAL)
|
|
assert data["title"] == "Critical: {}".format(
|
|
alert_rule.name
|
|
) # Pulls from trigger, not incident
|
|
assert data["status"] == "Critical" # Should pull from the action/trigger.
|
|
assert data["text"] == "4 events in the last 10 minutes"
|
|
assert data["ts"] == date_started
|
|
assert (
|
|
data["title_link"]
|
|
== f"http://testserver/organizations/baz/alerts/rules/details/{alert_rule.id}/?alert={incident.identifier}&referrer=metric_alert"
|
|
)
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
# Test the trigger "resolving"
|
|
data = incident_attachment_info(incident, IncidentStatus.CLOSED)
|
|
assert data["title"] == f"Resolved: {alert_rule.name}"
|
|
assert data["status"] == "Resolved"
|
|
assert data["text"] == "4 events in the last 10 minutes"
|
|
assert data["ts"] == date_started
|
|
assert (
|
|
data["title_link"]
|
|
== f"http://testserver/organizations/baz/alerts/rules/details/{alert_rule.id}/?alert={incident.identifier}&referrer=metric_alert"
|
|
)
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
# No trigger passed, uses incident as fallback
|
|
data = incident_attachment_info(incident, IncidentStatus.CLOSED)
|
|
assert data["title"] == f"Resolved: {alert_rule.name}"
|
|
assert data["status"] == "Resolved"
|
|
assert data["text"] == "4 events in the last 10 minutes"
|
|
assert data["ts"] == date_started
|
|
assert (
|
|
data["title_link"]
|
|
== f"http://testserver/organizations/baz/alerts/rules/details/{alert_rule.id}/?alert={incident.identifier}&referrer=metric_alert"
|
|
)
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_percent_change_alert(self):
|
|
# 1 hour comparison_delta
|
|
alert_rule = self.create_alert_rule(comparison_delta=60)
|
|
date_started = self.now
|
|
incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #1",
|
|
projects=[self.project],
|
|
alert_rule=alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=date_started,
|
|
)
|
|
trigger = self.create_alert_rule_trigger(alert_rule, CRITICAL_TRIGGER_LABEL, 100)
|
|
self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=incident
|
|
)
|
|
metric_value = 123.12
|
|
data = incident_attachment_info(incident, IncidentStatus.CRITICAL, metric_value)
|
|
assert (
|
|
data["text"]
|
|
== "Events 123% higher in the last 10 minutes compared to the same time one hour ago"
|
|
)
|
|
|
|
def test_percent_change_alert_custom_comparison_delta(self):
|
|
# 12 hour comparison_delta
|
|
alert_rule = self.create_alert_rule(comparison_delta=60 * 12)
|
|
date_started = self.now
|
|
incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #1",
|
|
projects=[self.project],
|
|
alert_rule=alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=date_started,
|
|
)
|
|
trigger = self.create_alert_rule_trigger(alert_rule, CRITICAL_TRIGGER_LABEL, 100)
|
|
self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=incident
|
|
)
|
|
metric_value = 123.12
|
|
data = incident_attachment_info(incident, IncidentStatus.CRITICAL, metric_value)
|
|
assert (
|
|
data["text"]
|
|
== "Events 123% higher in the last 10 minutes compared to the same time 720 minutes ago"
|
|
)
|
|
|
|
|
|
MOCK_NOW = timezone.now().replace(hour=13, minute=0, second=0, microsecond=0)
|
|
|
|
|
|
@freeze_time(MOCK_NOW)
|
|
class IncidentAttachmentInfoTestForCrashRateAlerts(TestCase, SnubaTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.now = timezone.now().replace(minute=0, second=0, microsecond=0)
|
|
self._5_min_ago = to_timestamp(self.now - timedelta(minutes=5))
|
|
self.date_started = self.now - timedelta(minutes=120)
|
|
|
|
def create_incident_and_related_objects(self, field="sessions"):
|
|
self.alert_rule = self.create_alert_rule(
|
|
query="",
|
|
aggregate=f"percentage({field}_crashed, {field}) AS _crash_rate_alert_aggregate",
|
|
dataset=Dataset.Sessions,
|
|
time_window=60,
|
|
)
|
|
self.incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #1",
|
|
projects=[self.project],
|
|
alert_rule=self.alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=self.now - timedelta(minutes=120),
|
|
)
|
|
trigger = self.create_alert_rule_trigger(self.alert_rule, CRITICAL_TRIGGER_LABEL, 95)
|
|
self.action = self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=self.incident
|
|
)
|
|
for _ in range(2):
|
|
self.store_session(self.build_session(status="exited", started=self._5_min_ago))
|
|
|
|
def test_with_incident_trigger_sessions(self):
|
|
self.create_incident_and_related_objects()
|
|
data = incident_attachment_info(self.incident, IncidentStatus.CRITICAL, 92)
|
|
|
|
assert data["title"] == f"Critical: {self.alert_rule.name}"
|
|
assert data["status"] == "Critical"
|
|
assert data["text"] == "92% sessions crash free rate in the last 60 minutes"
|
|
assert data["ts"] == self.date_started
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_with_incident_trigger_sessions_resolve(self):
|
|
self.create_incident_and_related_objects()
|
|
data = incident_attachment_info(self.incident, IncidentStatus.CLOSED)
|
|
assert data["title"] == f"Resolved: {self.alert_rule.name}"
|
|
assert data["status"] == "Resolved"
|
|
assert data["text"] == "100.0% sessions crash free rate in the last 60 minutes"
|
|
assert data["ts"] == self.date_started
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_with_incident_trigger_users(self):
|
|
self.create_incident_and_related_objects(field="users")
|
|
data = incident_attachment_info(self.incident, IncidentStatus.CRITICAL, 92)
|
|
assert data["title"] == f"Critical: {self.alert_rule.name}"
|
|
assert data["status"] == "Critical"
|
|
assert data["text"] == "92% users crash free rate in the last 60 minutes"
|
|
assert data["ts"] == self.date_started
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_with_incident_trigger_users_resolve(self):
|
|
self.create_incident_and_related_objects(field="users")
|
|
data = incident_attachment_info(self.incident, IncidentStatus.CLOSED)
|
|
assert data["title"] == f"Resolved: {self.alert_rule.name}"
|
|
assert data["status"] == "Resolved"
|
|
assert data["text"] == "100.0% users crash free rate in the last 60 minutes"
|
|
assert data["ts"] == self.date_started
|
|
assert (
|
|
data["logo_url"]
|
|
== "http://testserver/_static/{version}/sentry/images/sentry-email-avatar.png"
|
|
)
|
|
|
|
def test_with_incident_where_no_sessions_exist(self):
|
|
alert_rule = self.create_alert_rule(
|
|
query="",
|
|
aggregate="percentage(sessions_crashed, sessions) AS _crash_rate_alert_aggregate",
|
|
dataset=Dataset.Sessions,
|
|
time_window=60,
|
|
)
|
|
trigger = self.create_alert_rule_trigger(alert_rule, CRITICAL_TRIGGER_LABEL, 95)
|
|
incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #2",
|
|
projects=[self.project],
|
|
alert_rule=alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=self.now,
|
|
)
|
|
self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=incident
|
|
)
|
|
data = incident_attachment_info(incident, IncidentStatus.CRITICAL)
|
|
|
|
assert data["title"] == f"Critical: {alert_rule.name}"
|
|
assert data["status"] == "Critical"
|
|
assert data["text"] == "No sessions crash free rate in the last 60 minutes"
|
|
|
|
|
|
@freeze_time(MOCK_NOW)
|
|
class IncidentAttachmentInfoTestForMetricsCrashRateAlerts(
|
|
IncidentAttachmentInfoTestForCrashRateAlerts, BaseMetricsTestCase
|
|
):
|
|
def create_incident_and_related_objects(self, field="sessions"):
|
|
self.alert_rule = self.create_alert_rule(
|
|
query="",
|
|
aggregate=f"percentage({field}_crashed, {field}) AS _crash_rate_alert_aggregate",
|
|
dataset=Dataset.Metrics,
|
|
time_window=60,
|
|
)
|
|
self.incident = self.create_incident(
|
|
self.organization,
|
|
title="Incident #1",
|
|
projects=[self.project],
|
|
alert_rule=self.alert_rule,
|
|
status=IncidentStatus.CLOSED.value,
|
|
date_started=self.now - timedelta(minutes=120),
|
|
)
|
|
trigger = self.create_alert_rule_trigger(self.alert_rule, CRITICAL_TRIGGER_LABEL, 95)
|
|
self.action = self.create_alert_rule_trigger_action(
|
|
alert_rule_trigger=trigger, triggered_for_incident=self.incident
|
|
)
|
|
for _ in range(2):
|
|
self.store_session(self.build_session(status="exited", started=self._5_min_ago))
|