mirror of
https://github.com/getredash/redash.git
synced 2025-12-19 17:37:19 -05:00
Passing Request metadata to Alert destinations (#5230)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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 = [
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>'
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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 = [
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user