@ -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 | |||
from django.contrib.auth.models import User | |||
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): | |||
code = models.UUIDField(default=uuid.uuid4, editable=False) | |||
user = models.ForeignKey(User) | |||
enabled = models.BooleanField(default=True) | |||
timeout = models.DurationField(default=ONEDAY) | |||
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) |