Browse Source

Background worker to send notifications

pull/7/head
Pēteris Caune 10 years ago
parent
commit
aad4bd2ffb
8 changed files with 148 additions and 1 deletions
  1. +1
    -0
      hc/api/admin.py
  2. +27
    -0
      hc/api/management/commands/ensuretriggers.py
  3. +45
    -0
      hc/api/management/commands/sendalerts.py
  4. +35
    -0
      hc/api/migrations/0002_auto_20150616_0732.py
  5. +21
    -0
      hc/api/models.py
  6. +3
    -0
      hc/api/views.py
  7. +15
    -0
      hc/lib/emails.py
  8. +1
    -1
      hc/settings.py

+ 1
- 0
hc/api/admin.py View File

@ -2,6 +2,7 @@ from django.contrib import admin
from hc.api.models import Check
@admin.register(Check)
class ChecksAdmin(admin.ModelAdmin):
list_display = ("id", "code", "user", "last_ping")

+ 27
- 0
hc/api/management/commands/ensuretriggers.py View File

@ -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();
""")

+ 45
- 0
hc/api/management/commands/sendalerts.py View File

@ -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(".")

+ 35
- 0
hc/api/migrations/0002_auto_20150616_0732.py View File

@ -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)),
),
]

+ 21
- 0
hc/api/models.py View File

@ -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")

+ 3
- 0
hc/api/views.py View File

@ -11,6 +11,9 @@ def ping(request, code):
return HttpResponseBadRequest()
check.last_ping = timezone.now()
if check.status == "new":
check.status = "up"
check.save()
return HttpResponse()

+ 15
- 0
hc/lib/emails.py View File

@ -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)

+ 1
- 1
hc/settings.py View File

@ -85,7 +85,7 @@ DATABASES = {
'NAME': 'hc',
'USER': 'hc',
'PASSWORD': '',
'HOST': '192.168.1.111',
'HOST': '192.168.1.112',
'PORT': 5432,
'TEST': {'CHARSET': 'UTF8'}
}


Loading…
Cancel
Save