@ -0,0 +1,27 @@ | |||||
from django.core.management.base import BaseCommand | |||||
from django.db import connection | |||||
class Command(BaseCommand): | |||||
help = 'Ensures triggers exist in database' | |||||
def handle(self, *args, **options): | |||||
cursor = connection.cursor() | |||||
cursor.execute(""" | |||||
CREATE OR REPLACE FUNCTION update_alert_after() | |||||
RETURNS trigger AS $update_alert_after$ | |||||
BEGIN | |||||
IF NEW.last_ping IS NOT NULL THEN | |||||
NEW.alert_after := NEW.last_ping + NEW.timeout; | |||||
END IF; | |||||
RETURN NEW; | |||||
END; | |||||
$update_alert_after$ LANGUAGE plpgsql; | |||||
DROP TRIGGER IF EXISTS update_alert_after ON api_check; | |||||
CREATE TRIGGER update_alert_after | |||||
BEFORE INSERT OR UPDATE OF last_ping, timeout ON api_check | |||||
FOR EACH ROW EXECUTE PROCEDURE update_alert_after(); | |||||
""") |
@ -0,0 +1,45 @@ | |||||
import sys | |||||
import time | |||||
from django.core.management.base import BaseCommand | |||||
from django.utils import timezone | |||||
from hc.api.models import Check | |||||
from hc.lib.emails import send_status_notification | |||||
def _log(message): | |||||
sys.stdout.write(message) | |||||
sys.stdout.flush() | |||||
class Command(BaseCommand): | |||||
help = 'Ensures triggers exist in database' | |||||
def handle(self, *args, **options): | |||||
while True: | |||||
# Gone down? | |||||
query = Check.objects | |||||
query = query.filter(alert_after__lt=timezone.now()) | |||||
query = query.filter(enabled=True, status="up") | |||||
for check in query: | |||||
check.status = "down" | |||||
check.save() | |||||
_log("\nSending email about going down for %s\n" % check.code) | |||||
send_status_notification(check) | |||||
# Gone up? | |||||
query = Check.objects | |||||
query = query.filter(alert_after__gt=timezone.now()) | |||||
query = query.filter(enabled=True, status="down") | |||||
for check in query: | |||||
check.status = "up" | |||||
check.save() | |||||
_log("\nSending email about going up for %s\n" % check.code) | |||||
send_status_notification(check) | |||||
time.sleep(1) | |||||
_log(".") |
@ -0,0 +1,35 @@ | |||||
# -*- coding: utf-8 -*- | |||||
from __future__ import unicode_literals | |||||
from django.db import models, migrations | |||||
import datetime | |||||
class Migration(migrations.Migration): | |||||
dependencies = [ | |||||
('api', '0001_initial'), | |||||
] | |||||
operations = [ | |||||
migrations.AddField( | |||||
model_name='check', | |||||
name='alert_after', | |||||
field=models.DateTimeField(null=True, blank=True), | |||||
), | |||||
migrations.AddField( | |||||
model_name='check', | |||||
name='enabled', | |||||
field=models.BooleanField(default=True), | |||||
), | |||||
migrations.AddField( | |||||
model_name='check', | |||||
name='status', | |||||
field=models.CharField(max_length=6, choices=[('up', 'Up'), ('down', 'Down'), ('new', 'New')], default='new'), | |||||
), | |||||
migrations.AddField( | |||||
model_name='check', | |||||
name='timeout', | |||||
field=models.DurationField(choices=[(datetime.timedelta(0, 300), '5 minutes'), (datetime.timedelta(0, 600), '10 minutes'), (datetime.timedelta(0, 1800), '30 minutes'), (datetime.timedelta(0, 3600), '1 hour'), (datetime.timedelta(0, 7200), '2 hours'), (datetime.timedelta(0, 21600), '6 hours'), (datetime.timedelta(0, 43200), '12 hours'), (datetime.timedelta(1), '1 day'), (datetime.timedelta(2), '2 days'), (datetime.timedelta(7), '1 week'), (datetime.timedelta(14), '2 weeks')], default=datetime.timedelta(1)), | |||||
), | |||||
] |
@ -1,10 +1,31 @@ | |||||
from datetime import timedelta as td | |||||
import uuid | import uuid | ||||
from django.contrib.auth.models import User | from django.contrib.auth.models import User | ||||
from django.db import models | from django.db import models | ||||
STATUSES = (("up", "Up"), ("down", "Down"), ("new", "New")) | |||||
ONEDAY = td(days=1) | |||||
DURATIONS = ( | |||||
(td(minutes=5), "5 minutes"), | |||||
(td(minutes=10), "10 minutes"), | |||||
(td(minutes=30), "30 minutes"), | |||||
(td(hours=1), "1 hour"), | |||||
(td(hours=2), "2 hours"), | |||||
(td(hours=6), "6 hours"), | |||||
(td(hours=12), "12 hours"), | |||||
(ONEDAY, "1 day"), | |||||
(td(days=2), "2 days"), | |||||
(td(weeks=1), "1 week"), | |||||
(td(weeks=2), "2 weeks") | |||||
) | |||||
class Check(models.Model): | class Check(models.Model): | ||||
code = models.UUIDField(default=uuid.uuid4, editable=False) | code = models.UUIDField(default=uuid.uuid4, editable=False) | ||||
user = models.ForeignKey(User) | user = models.ForeignKey(User) | ||||
enabled = models.BooleanField(default=True) | |||||
timeout = models.DurationField(default=ONEDAY) | |||||
last_ping = models.DateTimeField(null=True, blank=True) | last_ping = models.DateTimeField(null=True, blank=True) | ||||
alert_after = models.DateTimeField(null=True, blank=True, editable=False) | |||||
status = models.CharField(max_length=6, choices=STATUSES, default="new") |
@ -0,0 +1,15 @@ | |||||
from django.core.mail import send_mail | |||||
def send_status_notification(check): | |||||
if check.status == "down": | |||||
subject = "Alert DOWN" | |||||
body = "Hi, the check %s has gone down" % check.code | |||||
elif check.status == "up": | |||||
subject = "Alert UP" | |||||
body = "Hi, the check %s has gone up" % check.code | |||||
else: | |||||
raise NotImplemented("Unexpected status: %s" % check.status) | |||||
send_mail(subject, body, '[email protected]', [check.user.email], | |||||
fail_silently=False) |