Skip to content

Commit

Permalink
Merge pull request #644 from toyama0919/feature/alert-to-hipchat
Browse files Browse the repository at this point in the history
Feature: send alert notifications to HipChat or web hook
  • Loading branch information
arikfr committed Dec 1, 2015
2 parents 995659e + 46f3e82 commit 0b389d5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 20 deletions.
29 changes: 18 additions & 11 deletions redash/models.py
Expand Up @@ -621,19 +621,26 @@ class Meta:
def all(cls):
return cls.select(Alert, User, Query).join(Query).switch(Alert).join(User)

def to_dict(self):
return {
'id': self.id,
'name': self.name,
'query': self.query.to_dict(),
'user': self.user.to_dict(),
'options': self.options,
'state': self.state,
'last_triggered_at': self.last_triggered_at,
'updated_at': self.updated_at,
'created_at': self.created_at
def to_dict(self, full=True):
d = {
'id': self.id,
'name': self.name,
'options': self.options,
'state': self.state,
'last_triggered_at': self.last_triggered_at,
'updated_at': self.updated_at,
'created_at': self.created_at
}

if full:
d['query'] = self.query.to_dict()
d['user'] = self.user.to_dict()
else:
d['query_id'] = self._data['query']
d['user_id'] = self._data['user']

return d

def evaluate(self):
data = json.loads(self.query.latest_query_data.data)
# todo: safe guard for empty
Expand Down
7 changes: 7 additions & 0 deletions redash/settings.py
Expand Up @@ -104,6 +104,13 @@ def all_settings():

HOST = os.environ.get('REDASH_HOST', '')

HIPCHAT_API_TOKEN = os.environ.get('REDASH_HIPCHAT_API_TOKEN', None)
HIPCHAT_ROOM_ID = os.environ.get('REDASH_HIPCHAT_ROOM_ID', None)

WEBHOOK_ENDPOINT = os.environ.get('REDASH_WEBHOOK_ENDPOINT', None)
WEBHOOK_USERNAME = os.environ.get('REDASH_WEBHOOK_USERNAME', None)
WEBHOOK_PASSWORD = os.environ.get('REDASH_WEBHOOK_PASSWORD', None)

# CORS settings for the Query Result API (and possbily future external APIs).
# In most cases all you need to do is set REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN
# to the calling domain (or domains in a comma separated list).
Expand Down
55 changes: 46 additions & 9 deletions redash/tasks.py
@@ -1,8 +1,14 @@
import time
import logging
import signal
import traceback
from flask.ext.mail import Message
import redis
import hipchat
import requests
import json
from redash.utils import json_dumps
from requests.auth import HTTPBasicAuth
from celery import Task
from celery.result import AsyncResult
from celery.utils.log import get_task_logger
Expand Down Expand Up @@ -252,24 +258,21 @@ def check_alerts_for_query(self, query_id):
continue

# message = Message
recipients = [s.email for s in alert.subscribers()]
logger.debug("Notifying: %s", recipients)
html = """
Check <a href="{host}/alerts/{alert_id}">alert</a> / check <a href="{host}/queries/{query_id}">query</a>.
""".format(host=settings.HOST, alert_id=alert.id, query_id=query.id)

with app.app_context():
message = Message(recipients=recipients,
subject="[{1}] {0}".format(alert.name, new_state.upper()),
html=html)
notify_mail(alert, html, new_state, app)

mail.send(message)
if settings.HIPCHAT_API_TOKEN:
notify_hipchat(alert, html, new_state)

if settings.WEBHOOK_ENDPOINT:
notify_webhook(alert, query, html, new_state)

def signal_handler(*args):
raise InterruptException


@celery.task(bind=True, base=BaseTask, track_started=True)
def execute_query(self, query, data_source_id, metadata):
signal.signal(signal.SIGINT, signal_handler)
Expand Down Expand Up @@ -325,7 +328,41 @@ def execute_query(self, query, data_source_id, metadata):
def record_event(event):
models.Event.record(event)


@celery.task(base=BaseTask)
def version_check():
run_version_check()

def notify_hipchat(alert, html, new_state):
try:
hipchat_client = hipchat.HipChat(token=settings.HIPCHAT_API_TOKEN)
message = '[' + new_state.upper() + '] ' + alert.name + '<br />' + html
hipchat_client.message_room(settings.HIPCHAT_ROOM_ID, settings.NAME, message, message_format='html')
except:
logger.exception("hipchat send ERROR.")

def notify_mail(alert, html, new_state, app):
recipients = [s.email for s in alert.subscribers()]
logger.debug("Notifying: %s", recipients)
try:
with app.app_context():
message = Message(recipients=recipients,
subject="[{1}] {0}".format(alert.name, new_state.upper()),
html=html)
mail.send(message)
except:
logger.exception("mail send ERROR.")

def notify_webhook(alert, query, html, new_state):
try:
data = {
'event': 'alert_state_change',
'alert': alert.to_dict(full=False),
'url_base': settings.HOST
}
headers = {'Content-Type': 'application/json'}
auth = HTTPBasicAuth(settings.WEBHOOK_USERNAME, settings.WEBHOOK_PASSWORD) if settings.WEBHOOK_USERNAME else None
resp = requests.post(settings.WEBHOOK_ENDPOINT, data=json_dumps(data), auth=auth, headers=headers)
if resp.status_code != 200:
logger.error("webhook send ERROR. status_code => {status}".format(status=resp.status_code))
except:
logger.exception("webhook send ERROR.")
1 change: 1 addition & 0 deletions requirements.txt
Expand Up @@ -34,3 +34,4 @@ pycrypto==2.6.1
funcy==1.5
raven==5.6.0
semver==2.2.1
python-simple-hipchat==0.4.0

0 comments on commit 0b389d5

Please sign in to comment.