Passing Request metadata to Alert destinations (#5230)

This commit is contained in:
Ivan Torgashov
2023-08-24 08:08:52 +05:00
committed by GitHub
parent 5eeeb5c62e
commit e18cd8f248
15 changed files with 28 additions and 26 deletions

View File

@@ -31,7 +31,7 @@ class BaseDestination(object):
def configuration_schema(cls):
return {}
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
raise NotImplementedError()
@classmethod

View File

@@ -29,7 +29,7 @@ class ChatWork(BaseDestination):
def icon(cls):
return "fa-comment"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
try:
# Documentation: http://developer.chatwork.com/ja/endpoint_rooms.html#POST-rooms-room_id-messages
url = "https://api.chatwork.com/v2/rooms/{room_id}/messages".format(room_id=options.get("room_id"))

View File

@@ -28,7 +28,7 @@ class Discord(BaseDestination):
def icon(cls):
return "fa-discord"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
# Documentation: https://birdie0.github.io/discord-webhooks-guide/discord_webhook.html
fields = [
{

View File

@@ -27,7 +27,7 @@ class Email(BaseDestination):
def icon(cls):
return "fa-envelope"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
recipients = [email for email in options.get("addresses", "").split(",") if email]
if not recipients:

View File

@@ -37,7 +37,7 @@ class HangoutsChat(BaseDestination):
def icon(cls):
return "fa-bolt"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
try:
if new_state == "triggered":
message = '<b><font color="#c0392b">Triggered</font></b>'

View File

@@ -24,7 +24,7 @@ class Mattermost(BaseDestination):
def icon(cls):
return "fa-bolt"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
if alert.custom_subject:
text = alert.custom_subject
elif new_state == "triggered":

View File

@@ -74,7 +74,7 @@ class MicrosoftTeamsWebhook(BaseDestination):
def icon(cls):
return "fa-bolt"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
"""
:type app: redash.Redash
"""

View File

@@ -40,7 +40,7 @@ class PagerDuty(BaseDestination):
def icon(cls):
return "creative-commons-pd-alt"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
if alert.custom_subject:
default_desc = alert.custom_subject
elif options.get("description"):

View File

@@ -21,7 +21,7 @@ class Slack(BaseDestination):
def icon(cls):
return "fa-slack"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
# Documentation: https://api.slack.com/docs/attachments
fields = [
{

View File

@@ -26,12 +26,13 @@ class Webhook(BaseDestination):
def icon(cls):
return "fa-bolt"
def notify(self, alert, query, user, new_state, app, host, options):
def notify(self, alert, query, user, new_state, app, host, metadata, options):
try:
data = {
"event": "alert_state_change",
"alert": serialize_alert(alert, full=False),
"url_base": host,
"metadata": metadata,
}
data["alert"]["description"] = alert.custom_body

View File

@@ -1318,10 +1318,10 @@ class NotificationDestination(BelongsToOrgMixin, db.Model):
return notification_destinations
def notify(self, alert, query, user, new_state, app, host):
def notify(self, alert, query, user, new_state, app, host, metadata):
schema = get_configuration_schema_for_destination_type(self.type)
self.options.set_schema(schema)
return self.destination.notify(alert, query, user, new_state, app, host, self.options)
return self.destination.notify(alert, query, user, new_state, app, host, metadata, self.options)
@generic_repr("id", "user_id", "destination_id", "alert_id")
@@ -1358,16 +1358,16 @@ class AlertSubscription(TimestampMixin, db.Model):
def all(cls, alert_id):
return AlertSubscription.query.join(User).filter(AlertSubscription.alert_id == alert_id)
def notify(self, alert, query, user, new_state, app, host):
def notify(self, alert, query, user, new_state, app, host, metadata):
if self.destination:
return self.destination.notify(alert, query, user, new_state, app, host)
return self.destination.notify(alert, query, user, new_state, app, host, metadata)
else:
# User email subscription, so create an email destination object
config = {"addresses": self.user.email}
schema = get_configuration_schema_for_destination_type("email")
options = ConfigurationContainer(config, schema)
destination = get_destination("email", options)
return destination.notify(alert, query, user, new_state, app, host, options)
return destination.notify(alert, query, user, new_state, app, host, metadata, options)
@generic_repr("id", "trigger", "user_id", "org_id")

View File

@@ -8,11 +8,11 @@ from redash.worker import get_job_logger, job
logger = get_job_logger(__name__)
def notify_subscriptions(alert, new_state):
def notify_subscriptions(alert, new_state, metadata):
host = utils.base_url(alert.query_rel.org)
for subscription in alert.subscriptions:
try:
subscription.notify(alert, alert.query_rel, subscription.user, new_state, current_app, host)
subscription.notify(alert, alert.query_rel, subscription.user, new_state, current_app, host, metadata)
except Exception:
logger.exception("Error with processing destination")
@@ -26,7 +26,7 @@ def should_notify(alert, new_state):
@job("default", timeout=300)
def check_alerts_for_query(query_id):
def check_alerts_for_query(query_id, metadata):
logger.debug("Checking query %d for alerts", query_id)
query = models.Query.query.get(query_id)
@@ -51,4 +51,4 @@ def check_alerts_for_query(query_id):
logger.debug("Skipping notification (alert muted).")
continue
notify_subscriptions(alert, new_state)
notify_subscriptions(alert, new_state, metadata)

View File

@@ -227,7 +227,7 @@ class QueryExecutor(object):
models.db.session.commit() # make sure that alert sees the latest query result
self._log_progress("checking_alerts")
for query_id in updated_query_ids:
check_alerts_for_query.delay(query_id)
check_alerts_for_query.delay(query_id, self.metadata)
self._log_progress("finished")
result = query_result.id

View File

@@ -108,7 +108,7 @@ def test_discord_notify_calls_requests_post():
app = mock.Mock()
host = "https://localhost:5000"
options = {"url": "https://discordapp.com/api/webhooks/test"}
metadata = {"Scheduled": False}
new_state = Alert.TRIGGERED_STATE
destination = Discord(options)
@@ -117,7 +117,7 @@ def test_discord_notify_calls_requests_post():
mock_response.status_code = 204
mock_post.return_value = mock_response
destination.notify(alert, query, user, new_state, app, host, options)
destination.notify(alert, query, user, new_state, app, host, metadata, options)
expected_payload = {
"content": "Test custom subject",

View File

@@ -12,7 +12,7 @@ class TestCheckAlertsForQuery(BaseTestCase):
Alert.evaluate = MagicMock(return_value=Alert.TRIGGERED_STATE)
alert = self.factory.create_alert()
check_alerts_for_query(alert.query_id)
check_alerts_for_query(alert.query_id, metadata={"Scheduled": False})
self.assertTrue(redash.tasks.alerts.notify_subscriptions.called)
@@ -21,7 +21,7 @@ class TestCheckAlertsForQuery(BaseTestCase):
Alert.evaluate = MagicMock(return_value=Alert.OK_STATE)
alert = self.factory.create_alert()
check_alerts_for_query(alert.query_id)
check_alerts_for_query(alert.query_id, metadata={"Scheduled": False})
self.assertFalse(redash.tasks.alerts.notify_subscriptions.called)
@@ -30,7 +30,7 @@ class TestCheckAlertsForQuery(BaseTestCase):
Alert.evaluate = MagicMock(return_value=Alert.TRIGGERED_STATE)
alert = self.factory.create_alert(options={"muted": True})
check_alerts_for_query(alert.query_id)
check_alerts_for_query(alert.query_id, metadata={"Scheduled": False})
self.assertFalse(redash.tasks.alerts.notify_subscriptions.called)
@@ -39,7 +39,7 @@ class TestNotifySubscriptions(BaseTestCase):
def test_calls_notify_for_subscribers(self):
subscription = self.factory.create_alert_subscription()
subscription.notify = MagicMock()
notify_subscriptions(subscription.alert, Alert.OK_STATE)
notify_subscriptions(subscription.alert, Alert.OK_STATE, metadata={"Scheduled": False})
subscription.notify.assert_called_with(
subscription.alert,
subscription.alert.query_rel,
@@ -47,4 +47,5 @@ class TestNotifySubscriptions(BaseTestCase):
Alert.OK_STATE,
ANY,
ANY,
ANY,
)