From 575e4c6f26d563c18602cd6ab242af31bf78ca81 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 21 Aug 2014 18:07:19 +0000 Subject: [PATCH 01/11] Fixing bugs --- main/models.py | 4 +++- urls.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/main/models.py b/main/models.py index b472064..013e154 100644 --- a/main/models.py +++ b/main/models.py @@ -264,7 +264,9 @@ def set_state(self,status,last_value,extra={}): new_mean = last_value #Calculate new std. dont update if above 2 stds - if self.last_std == None: + if last_value == None or new_mean == None: + new_std = 0 + elif self.last_std == None: new_std = abs(last_value-new_mean) elif abs(last_value-new_mean)>2*self.last_std: new_std = abs(self.last_std) diff --git a/urls.py b/urls.py index 00fb9e4..1147918 100644 --- a/urls.py +++ b/urls.py @@ -1,5 +1,7 @@ from django.conf.urls.defaults import * from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.contrib.auth.decorators import login_required +from django.views.static import serve from django.conf import settings urlpatterns = patterns('', @@ -7,7 +9,7 @@ url('^social_auth/', include('social_auth.urls')), url('^mobile/', include('momonitor.mobile.urls',namespace="mobile")), url('^slideshow/', include('momonitor.slideshow.urls',namespace="slideshow")), - url(r'^media/(?P.*)$', 'django.views.static.serve', { + url(r'^media/(?P.*)$', login_required(serve), { 'document_root': settings.MEDIA_ROOT}), ) From 7a7672fec5ce80b6b45e0c488de78bafec6068d5 Mon Sep 17 00:00:00 2001 From: Peter Linnartz Date: Fri, 22 Aug 2014 11:16:50 -0700 Subject: [PATCH 02/11] fix alert type override bug RB_ID=436713 --- main/models.py | 56 +++++++++++++++++++++++++------------------------- main/tests.py | 33 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 main/tests.py diff --git a/main/models.py b/main/models.py index 013e154..bd4a257 100644 --- a/main/models.py +++ b/main/models.py @@ -37,7 +37,7 @@ class Service(models.Model): #Default values if not specified in the check frequency = models.CharField(max_length=128,default="*/5 * * * *") #cron format failures_before_alert = models.IntegerField(default=1) - umpire_range = models.IntegerField(default=300) + umpire_range = models.IntegerField(default=300) alert_type = models.CharField(max_length=64,choices=ALERT_CHOICES,default="none") def __unicode__(self): @@ -97,7 +97,7 @@ def _send_alert_email(self,description): reverse("main:service",kwargs={'service_id':self.id})) }) ) - + send_mail("MOMONITOR EVENT TRIGGERED", email_msg, settings.SERVER_EMAIL, @@ -138,7 +138,7 @@ class Meta: abstract=True name = models.CharField(max_length=256) - description = models.TextField(null=True,blank=True) + description = models.TextField(null=True,blank=True) service = models.ForeignKey(Service,related_name="%(class)s") silenced = models.BooleanField(default=False) alert_type = models.CharField(max_length=64,choices=ALERT_CHOICES,null=True,blank=True) @@ -175,7 +175,7 @@ def set_state(self,status,last_value,extra={}): cache.set(self._redis_key,json.dumps(state),timeout=0) @property - def status(self): + def status(self): return self._get_state().get("status",STATUS_UNKNOWN) @property @@ -192,7 +192,7 @@ def num_failures(self): def send_alert(self): if not self.silenced: - self.service.send_alert(self.description or self.name) + self.service.send_alert(self.description or self.name, self.alert_type) else: logging.info("Triggered alert on %s, but it is silenced" % self.name) @@ -262,7 +262,7 @@ def set_state(self,status,last_value,extra={}): new_mean = self.history_value*.9 + last_value*.1 else: new_mean = last_value - + #Calculate new std. dont update if above 2 stds if last_value == None or new_mean == None: new_std = 0 @@ -325,8 +325,8 @@ def _standardize_minutes(self,cur_time): def error_lower_bound(self): if self.umpire_check_type == "static": return self.umpire_min - else: - return self.history_value*(1-self.umpire_percent_error) + else: + return self.history_value*(1-self.umpire_percent_error) @property def error_upper_bound(self): @@ -383,8 +383,8 @@ def _update_status_dynamic(self): def update_status(self): value = None status = STATUS_UNKNOWN - - if self.umpire_check_type=="static": + + if self.umpire_check_type=="static": umpire_min,umpire_max = self._update_status_static() else: umpire_min,umpire_max = self._update_status_dynamic() @@ -406,7 +406,7 @@ def update_status(self): try: res = requests.get(endpoint) res_data = res.json() - if res.status_code == 200: + if res.status_code == 200: value = res_data['value'] status = STATUS_GOOD else: @@ -433,8 +433,8 @@ def update_status(self): self._update_history() ''' -This check looks at a specific field in a -serialized response and applies an arithmatic +This check looks at a specific field in a +serialized response and applies an arithmatic check to that value ''' class CompareServiceCheck(ServiceCheck): @@ -453,7 +453,7 @@ def last_value(self): except: return last_value - def update_status(self): + def update_status(self): value = None status = STATUS_UNKNOWN @@ -473,8 +473,8 @@ def update_status(self): logging.error("Failed to parse json data correctly. Can't index %s in list of length" % (subfield,len(res_data))) status = STATUS_UNKNOWN res_data = None - break - + break + else: if not res_data.has_key(subfield): logging.error("Bad field path for check %s and field path %s" % (self.name,self.field)) @@ -485,9 +485,9 @@ def update_status(self): elif self.serialization=="plaintext": res_data = res.text - + try: - #attempt to cast as float + #attempt to cast as float value = round(float(res_data),2) compared_value = round(float(self.compared_value),2) except ValueError: @@ -504,7 +504,7 @@ def update_status(self): status = STATUS_GOOD if value >= compared_value else STATUS_BAD elif self.comparator == "<": status = STATUS_GOOD if value < compared_value else STATUS_BAD - elif self.comparator == "<=": + elif self.comparator == "<=": status = STATUS_GOOD if value <= compared_value else STATUS_BAD elif self.comparator == "contains": status = STATUS_GOOD if compared_value in value else STATUS_BAD @@ -512,7 +512,7 @@ def update_status(self): status= STATUS_BAD except (requests.exceptions.ConnectionError,requests.exceptions.Timeout) as e: - logging.error("Unable to connect to the server") + logging.error("Unable to connect to the server") status = STATUS_BAD self.set_state(status=status,last_value=value) @@ -534,10 +534,10 @@ def update_status(self): module = eval("parent_module.%s" % self.file_name) value,succeeded = module.run() status = STATUS_GOOD if succeeded else STATUS_BAD - except Exception as e: + except Exception as e: status = STATUS_UNKNOWN value = str(e) - + self.set_state(status=status,last_value=value) class SensuServiceCheck(ServiceCheck): @@ -547,11 +547,11 @@ class SensuServiceCheck(ServiceCheck): def get_result_data(self): if not self.last_updated: logging.info("Requested result data when no data available") - return [] + return [] endpoint = "%s/aggregates/%s/%s?results=true" % (settings.SENSU_API_ENDPOINT, self.sensu_check_name, - self.last_updated) + self.last_updated) res = requests.get(endpoint) if not res.status_code==200: logging.warning("Failed to get data from sensu server") @@ -585,16 +585,16 @@ def update_status(self): value = "%s/%s/%s" % (aggregate_data.get("ok",0), aggregate_data.get("critical",0), - aggregate_data.get("warning",0) + aggregate_data.get("unknown",0) + aggregate_data.get("warning",0) + aggregate_data.get("unknown",0) ) - + except (requests.exceptions.ConnectionError,requests.exceptions.Timeout) as e: logging.error("Failed to connect with sensu api server") - + extra = {} if last_aggregate: extra.update({"last_updated":last_aggregate}) - + self.set_state(status=status,last_value=value,extra=extra) RESOURCES = [ diff --git a/main/tests.py b/main/tests.py new file mode 100644 index 0000000..dd110d7 --- /dev/null +++ b/main/tests.py @@ -0,0 +1,33 @@ +from django.utils import unittest +import mock + +from momonitor.main.constants import STATUS_BAD +from momonitor.main.models import Service, SimpleServiceCheck + + +class ServiceCheckAlertTest(unittest.TestCase): + def setUp(self): + self.service = Service.objects.create( + name='test service', + alert_type='pagerduty') + self.service_check = SimpleServiceCheck.objects.create( + endpoint="http://twitter.com", + service=self.service) + + self.service._send_alert_pagerduty = mock.Mock() + self.service._send_alert_email = mock.Mock() + + def test_service_check_alert(self): + self.service_check.set_state(STATUS_BAD, None) + + self.service._send_alert_pagerduty.assert_called_with('') + assert not self.service._send_alert_email.called + + def test_service_check_alert_override(self): + self.service_check.alert_type = 'email' + self.service_check.save() + + self.service_check.set_state(STATUS_BAD, None) + + assert not self.service._send_alert_pagerduty.called + self.service._send_alert_email.assert_called_with('') From de90abb5c2ffe6449a9edbe3eaf05832e19e01ab Mon Sep 17 00:00:00 2001 From: Peter Linnartz Date: Tue, 2 Sep 2014 14:46:50 -0700 Subject: [PATCH 03/11] add a more descriptive email alert subject RB_ID=443589 --- main/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/models.py b/main/models.py index bd4a257..2ebff0b 100644 --- a/main/models.py +++ b/main/models.py @@ -90,6 +90,7 @@ def _send_alert_email(self,description): if not self.email_contact: logging.warning("No email contact for service %s" % self.name) try: + title = "{} Service Check Failed: {}".format(self.name, description) email_msg = get_template("alert_email.txt").render( Context({"description":description, "service_name":self.name, @@ -98,7 +99,7 @@ def _send_alert_email(self,description): }) ) - send_mail("MOMONITOR EVENT TRIGGERED", + send_mail(title, email_msg, settings.SERVER_EMAIL, [self.email_contact,], From 17610c815e7c804f258ea95d7b0bdb58788cad48 Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Wed, 10 Sep 2014 18:19:55 -0700 Subject: [PATCH 04/11] Update django-tastypie version. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 65b3138..4386e51 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ croniter==0.3.3 django-breadcrumbs==1.1.3-p1 django-redis==3.1.6 django-social-auth==0.7.18 -django-tastypie==0.9.12-alpha +django-tastypie==0.9.14 gevent==0.13.8 greenlet==0.4.0 gunicorn==0.17.2 From 03d09eb79eabd642bc30dfcce57f84b29cc2dcfe Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Wed, 10 Sep 2014 20:20:27 -0700 Subject: [PATCH 05/11] Update README. --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e31006e..1d93453 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,15 @@ To install Momonitor, follow the below steps: * python manage.py schemamigration main --initial * python manage.py syncdb * python manage.py migrate main +* python manage.py migrate social_auth * python manage.py runserver +Additionally, to get Momonitor working fully, you'll need to: + +* Create a crontab similar to the provided `crontab.template` +* Start redis-server on port 6379 + * This is Redis's default port, so you can do this by simply running `redis-server` + # Overview ## What it is @@ -26,7 +33,7 @@ Momonitor is a simple tool that polls URL endpoints and runs checks on the respe Essentially two types of things exist in Momonitor: services and checks. Services and checks each have a status (good, bad, or unknown). Services are a collection checks that test a specific system. Multiple types of checks exist; each tests different aspects of the target system. ## What it isn't -Momonitor is not a tool for finding errors on single machines. It lacks the functionality at peforming specific checks on specific machines. This is better done using a tool likSensu. Momonitor integration with sensu is in the works. +Momonitor is not a tool for finding errors on single machines. It lacks the functionality at peforming specific checks on specific machines. This is better done using a tool like Sensu. Momonitor integration with sensu is in the works. ### Types of Checks * Simple Check - check a single URL endpoint and report whether the response was a 200 or 500 From 2278f746423a690dd8dbe5043f4bf4de1e5e4466 Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Wed, 10 Sep 2014 22:50:00 -0700 Subject: [PATCH 06/11] Basic change from silenced bool to silenced_until timestamp. --- main/models.py | 8 ++++++-- main/templates/main/index.html | 2 +- main/templates/main/modal_forms/code_check.html | 3 ++- main/templates/main/modal_forms/compare_check.html | 3 ++- main/templates/main/modal_forms/sensu_check.html | 3 ++- main/templates/main/modal_forms/simple_check.html | 3 ++- main/templates/main/modal_forms/umpire_check.html | 3 ++- main/templates/main/tables/code_check.html | 4 ++-- main/templates/main/tables/compare_check.html | 4 ++-- main/templates/main/tables/sensu_check.html | 4 ++-- main/templates/main/tables/simple_check.html | 4 ++-- main/templates/main/tables/umpire_check.html | 4 ++-- mobile/templates/mobile/checks/base.html | 4 ++-- 13 files changed, 29 insertions(+), 20 deletions(-) diff --git a/main/models.py b/main/models.py index 2ebff0b..cdd5d54 100644 --- a/main/models.py +++ b/main/models.py @@ -141,7 +141,7 @@ class Meta: name = models.CharField(max_length=256) description = models.TextField(null=True,blank=True) service = models.ForeignKey(Service,related_name="%(class)s") - silenced = models.BooleanField(default=False) + silenced_until = models.IntegerField(default=0) # This is a timestamp (seconds since unix epoch). alert_type = models.CharField(max_length=64,choices=ALERT_CHOICES,null=True,blank=True) frequency = models.CharField(max_length=128,null=True,blank=True) failures_before_alert = models.IntegerField(null=True,blank=True) @@ -149,6 +149,10 @@ class Meta: def __unicode__(self): return "%s: %s" % (self.service.name,self.name) + @property + def is_silenced(self): + return time.time() < self.silenced_until + @property def _redis_key(self): return "%s:::%s" % (self.resource_name,self.id) @@ -192,7 +196,7 @@ def num_failures(self): return self._get_state().get("num_failures",0) def send_alert(self): - if not self.silenced: + if not self.is_silenced: self.service.send_alert(self.description or self.name, self.alert_type) else: logging.info("Triggered alert on %s, but it is silenced" % self.name) diff --git a/main/templates/main/index.html b/main/templates/main/index.html index 3c5a3a5..4e8acbb 100644 --- a/main/templates/main/index.html +++ b/main/templates/main/index.html @@ -20,7 +20,7 @@

All Services

{% if services %} {% for service in services %} - {{service.name}} {% if check.silenced or service.silenced %}silenced{% endif %} + {{service.name}} {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/main/templates/main/modal_forms/code_check.html b/main/templates/main/modal_forms/code_check.html index 589d4e3..ae7a889 100644 --- a/main/templates/main/modal_forms/code_check.html +++ b/main/templates/main/modal_forms/code_check.html @@ -11,7 +11,8 @@ {{form.description}}
- + + {{form.silenced_until}} {{form.code_file}}
diff --git a/main/templates/main/modal_forms/compare_check.html b/main/templates/main/modal_forms/compare_check.html index f7c2571..11da57a 100644 --- a/main/templates/main/modal_forms/compare_check.html +++ b/main/templates/main/modal_forms/compare_check.html @@ -11,7 +11,8 @@ {{form.description}}
- + + {{form.silenced_until}} {{form.endpoint}} diff --git a/main/templates/main/modal_forms/sensu_check.html b/main/templates/main/modal_forms/sensu_check.html index fd4949d..7e6a04d 100644 --- a/main/templates/main/modal_forms/sensu_check.html +++ b/main/templates/main/modal_forms/sensu_check.html @@ -11,7 +11,8 @@ {{form.description}}
- + + {{form.silenced_until}} {{form.sensu_check_name}}
diff --git a/main/templates/main/modal_forms/simple_check.html b/main/templates/main/modal_forms/simple_check.html index 5dcd0c4..7444571 100644 --- a/main/templates/main/modal_forms/simple_check.html +++ b/main/templates/main/modal_forms/simple_check.html @@ -11,7 +11,8 @@ {{form.description}}
- + + {{form.silenced_until}} {{form.endpoint}} diff --git a/main/templates/main/modal_forms/umpire_check.html b/main/templates/main/modal_forms/umpire_check.html index 500cf63..b04616f 100644 --- a/main/templates/main/modal_forms/umpire_check.html +++ b/main/templates/main/modal_forms/umpire_check.html @@ -15,7 +15,8 @@ {{form.umpire_range_type}}
- + + {{form.silenced_until}} {{form.umpire_metric}}
diff --git a/main/templates/main/tables/code_check.html b/main/templates/main/tables/code_check.html index a051d0f..6765b12 100644 --- a/main/templates/main/tables/code_check.html +++ b/main/templates/main/tables/code_check.html @@ -19,9 +19,9 @@

Code Checks {% if service.codeservicecheck.count %} {% for check in service.codeservicecheck.all|dictsort:"id" %} - + - {{check.name}} {% if check.silenced or service.silenced %}silenced{% endif %} + {{check.name}} {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/main/templates/main/tables/compare_check.html b/main/templates/main/tables/compare_check.html index 75f2ae7..30475ac 100644 --- a/main/templates/main/tables/compare_check.html +++ b/main/templates/main/tables/compare_check.html @@ -22,10 +22,10 @@

Compare Checks {% if service.compareservicecheck.count %} {% for check in service.compareservicecheck.all|dictsort:"id" %} - + {{check.name}} - {% if check.silenced or service.silenced %}silenced{% endif %} + {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/main/templates/main/tables/sensu_check.html b/main/templates/main/tables/sensu_check.html index 44c1884..293c8ea 100644 --- a/main/templates/main/tables/sensu_check.html +++ b/main/templates/main/tables/sensu_check.html @@ -19,9 +19,9 @@

Sensu Checks {% if service.sensuservicecheck.count %} {% for check in service.sensuservicecheck.all|dictsort:"id" %} - + - {{check.name}} {% if check.silenced or service.silenced %}silenced{% endif %} + {{check.name}} {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/main/templates/main/tables/simple_check.html b/main/templates/main/tables/simple_check.html index ef869c9..c382c91 100644 --- a/main/templates/main/tables/simple_check.html +++ b/main/templates/main/tables/simple_check.html @@ -19,9 +19,9 @@

Simple Checks {% if service.simpleservicecheck.count %} {% for check in service.simpleservicecheck.all|dictsort:"id" %} - + - {{check.name}} {% if check.silenced or service.silenced %}silenced{% endif %} + {{check.name}} {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/main/templates/main/tables/umpire_check.html b/main/templates/main/tables/umpire_check.html index b8079e3..8acda0d 100644 --- a/main/templates/main/tables/umpire_check.html +++ b/main/templates/main/tables/umpire_check.html @@ -18,10 +18,10 @@

Umpire Checks {% if service.umpireservicecheck.count %} {% for check in service.umpireservicecheck.all|dictsort:"id" %} - + {{check.name}} - {% if check.silenced or service.silenced %}silenced{% endif %} + {% if check.is_silenced or service.silenced %}silenced{% endif %} diff --git a/mobile/templates/mobile/checks/base.html b/mobile/templates/mobile/checks/base.html index b61977c..6fe7676 100644 --- a/mobile/templates/mobile/checks/base.html +++ b/mobile/templates/mobile/checks/base.html @@ -3,11 +3,11 @@ {% block body %}
-

Check: {{check.name}} {% if check.silenced or check.service.silenced %}(silenced){% endif %}

+

Check: {{check.name}} {% if check.is_silenced or check.service.silenced %}(silenced){% endif %}

Back {% if not check.service.silenced %} - {% if check.silenced %}Unsilence{% else %}Silence{% endif %} + {% if check.is_silenced %}Unsilence{% else %}Silence{% endif %} {% endif %}
From b4fada54fc0396019648d3fd0d0209b414f44bc4 Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Thu, 11 Sep 2014 00:23:35 -0700 Subject: [PATCH 07/11] Add setter buttons and dynamic description for silenced_until. --- common/static/js/momonitoring.js | 72 +++++++++++++++++++ .../main/modal_forms/simple_check.html | 4 ++ 2 files changed, 76 insertions(+) diff --git a/common/static/js/momonitoring.js b/common/static/js/momonitoring.js index 0d3e8dc..edd1b4a 100644 --- a/common/static/js/momonitoring.js +++ b/common/static/js/momonitoring.js @@ -133,6 +133,66 @@ function deleteResource(urlEndpoint) { }); } +function setSilencedDescriptionFromField() { + if ($("#id_silenced_until").length === 0) { + return; + } + + // Both of these vars are timestamps (seconds since the epoch). + var now = new Date().getTime() / 1000; + var silencedUntil = parseInt($("#id_silenced_until").val()); + + function round(num) { + // Rounds 1.8 to 2, but 1.79 to 1. + return Math.floor(num + 0.2); + } + + var diffSeconds = round(silencedUntil - now); + var diffMinutes = round(diffSeconds / 60); + var diffHours = round(diffMinutes / 60); + var diffDays = round(diffHours / 24); + + var description; + + if (2000000000 <= silencedUntil) { + description = "Silenced forever"; + } else if (silencedUntil < now) { + description = "Not silenced"; + } else if (diffDays >= 2) { + description = "Silenced for ~" + diffDays + " day(s)"; + } else if (diffHours >= 2) { + description = "Silenced for ~" + diffHours + " hour(s)"; + } else if (diffMinutes >= 1) { + description = "Silenced for " + diffMinutes + " minute(s)"; + } else { + description = "Silenced for " + diffSeconds + " second(s)"; + } + + $("#silenced_description").text(description); +} + +function setSilencedFor(secondsFromNow) { + var now = new Date().getTime() / 1000; // Timestamp (seconds since the epoch). + var silencedUntil = Math.floor(now + secondsFromNow); + $("#id_silenced_until").val(silencedUntil); + setSilencedDescriptionFromField(); +} + +function setSilencedForever() { + $("#id_silenced_until").val(2000000000); + setSilencedDescriptionFromField(); +} + +function setUnSilenced() { + $("#id_silenced_until").val(0); + setSilencedDescriptionFromField(); +} + +function setSilencedForXHours() { + var hoursToSilenceFor = parseFloat($("#silence_hours").val()); + setSilencedFor(hoursToSilenceFor * 60 * 60); +} + function init(container$) { console.log("hello") if(typeof(container$)==='undefined') container$ = $('body'); @@ -240,6 +300,18 @@ function init(container$) { }); }); + setSilencedDescriptionFromField(); + $('#id_silenced_until',container$).change(setSilencedDescriptionFromField); + $('#id_silenced_until',container$).click(setSilencedDescriptionFromField); + $('#id_silenced_until',container$).focus(setSilencedDescriptionFromField); + $('#id_silenced_until',container$).blur(setSilencedDescriptionFromField); + $('#id_silenced_until',container$).keyup(setSilencedDescriptionFromField); + $('#id_silenced_until',container$).keydown(setSilencedDescriptionFromField); + + $('#unsilence',container$).click(setUnSilenced); + $('#silence_for_x_hours',container$).click(setSilencedForXHours); + $('#silence_forever',container$).click(setSilencedForever); + $('form',container$).each(function() { var form$ = $(this); $('input',form$).keypress(function(event) { diff --git a/main/templates/main/modal_forms/simple_check.html b/main/templates/main/modal_forms/simple_check.html index 7444571..f438892 100644 --- a/main/templates/main/modal_forms/simple_check.html +++ b/main/templates/main/modal_forms/simple_check.html @@ -11,6 +11,10 @@ {{form.description}}
+ + + + {{form.silenced_until}} From 449c5a3f8e6f730d93de8c03ca897958f2b8ec0b Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Thu, 11 Sep 2014 00:29:17 -0700 Subject: [PATCH 08/11] Move things around, improve style. --- main/templates/main/modal_forms/simple_check.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main/templates/main/modal_forms/simple_check.html b/main/templates/main/modal_forms/simple_check.html index f438892..c8937d3 100644 --- a/main/templates/main/modal_forms/simple_check.html +++ b/main/templates/main/modal_forms/simple_check.html @@ -9,18 +9,18 @@ {{form.name}} {{form.description}} + + {{form.endpoint}} + + {{form.timeout}}
- + + + {{form.silenced_until}} - - {{form.silenced_until}} - - {{form.endpoint}} - - {{form.timeout}}
From 70b5692e32ed672114ebcfa199bcd642dd89be25 Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Thu, 11 Sep 2014 00:40:44 -0700 Subject: [PATCH 09/11] Apply the silenced_until changes to the other 4 forms as well. --- .../main/modal_forms/code_check.html | 8 +++-- .../main/modal_forms/compare_check.html | 12 +++++--- .../main/modal_forms/sensu_check.html | 8 +++-- .../main/modal_forms/umpire_check.html | 30 +++++++++++-------- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/main/templates/main/modal_forms/code_check.html b/main/templates/main/modal_forms/code_check.html index ae7a889..4b44014 100644 --- a/main/templates/main/modal_forms/code_check.html +++ b/main/templates/main/modal_forms/code_check.html @@ -9,12 +9,16 @@ {{form.name}} {{form.description}} + + {{form.code_file}}

+ {{form.silenced_until}} - - {{form.code_file}} + + +
diff --git a/main/templates/main/modal_forms/compare_check.html b/main/templates/main/modal_forms/compare_check.html index 11da57a..37c5f21 100644 --- a/main/templates/main/modal_forms/compare_check.html +++ b/main/templates/main/modal_forms/compare_check.html @@ -9,10 +9,6 @@ {{form.name}} {{form.description}} -
-
- - {{form.silenced_until}} {{form.endpoint}} @@ -22,6 +18,14 @@ {{form.comparator}} {{form.compared_value}}
+
+ + + {{form.silenced_until}} + + + +

diff --git a/main/templates/main/modal_forms/sensu_check.html b/main/templates/main/modal_forms/sensu_check.html index 7e6a04d..2e2e760 100644 --- a/main/templates/main/modal_forms/sensu_check.html +++ b/main/templates/main/modal_forms/sensu_check.html @@ -9,12 +9,16 @@ {{form.name}} {{form.description}} + + {{form.sensu_check_name}}
+ {{form.silenced_until}} - - {{form.sensu_check_name}} + + +
diff --git a/main/templates/main/modal_forms/umpire_check.html b/main/templates/main/modal_forms/umpire_check.html index b04616f..42eacb2 100644 --- a/main/templates/main/modal_forms/umpire_check.html +++ b/main/templates/main/modal_forms/umpire_check.html @@ -13,31 +13,37 @@ {{form.umpire_check_type}} {{form.umpire_range_type}} + + {{form.umpire_metric}}
+ {{form.silenced_until}} - - {{form.umpire_metric}} + + + +
- - {{form.umpire_min}} - - {{form.umpire_max}} + + {{form.umpire_min}} + + {{form.umpire_max}}
- - {{form.umpire_percent_error}} - Error range will be computed over time based on past history + + {{form.umpire_percent_error}} + Error range will be computed over time based on past history
+
- - {{form.umpire_range}} + + {{form.umpire_range}}
- Range will be computed from the beginning of the day + Range will be computed from the beginning of the day
From 9982b64b95e3b5c5794711872c568dfcefb4cf4a Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Fri, 12 Sep 2014 14:31:36 -0700 Subject: [PATCH 10/11] Copy the changes to models.py to change silenced to silenced_until. --- main/models/service_check.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/main/models/service_check.py b/main/models/service_check.py index 1306766..76d22ed 100644 --- a/main/models/service_check.py +++ b/main/models/service_check.py @@ -19,7 +19,7 @@ class Meta: name = models.CharField(max_length=256) description = models.TextField(null=True,blank=True) service = models.ForeignKey(Service,related_name="%(class)s") - silenced = models.BooleanField(default=False) + silenced_until = models.IntegerField(default=0) # This is a timestamp (seconds since unix epoch). alert_type = models.CharField(max_length=64,choices=ALERT_CHOICES,null=True,blank=True) frequency = models.CharField(max_length=128,null=True,blank=True) failures_before_alert = models.IntegerField(null=True,blank=True) @@ -27,6 +27,10 @@ class Meta: def __unicode__(self): return "%s: %s" % (self.service.name,self.name) + @property + def is_silenced(self): + return time.time() < self.silenced_until + @property def _redis_key(self): return "%s:::%s" % (self.resource_name,self.id) @@ -70,7 +74,7 @@ def num_failures(self): return self._get_state().get("num_failures",0) def send_alert(self,alert_type=None): - if not self.silenced: + if not self.is_silenced: self.service.send_alert(self.description or self.name,alert_type) else: logging.info("Triggered alert on %s, but it is silenced" % self.name) From 2fc1cbf61de57be2be0ca930166bdec461caab96 Mon Sep 17 00:00:00 2001 From: Simon Radford Date: Fri, 12 Sep 2014 14:57:04 -0700 Subject: [PATCH 11/11] Merge the last of Peter's changes which failed to merge over (due to models.py file being split up). --- main/models/service.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/models/service.py b/main/models/service.py index cfdf26b..205ce14 100644 --- a/main/models/service.py +++ b/main/models/service.py @@ -77,6 +77,7 @@ def _send_alert_email(self,description): if not self.email_contact: logging.warning("No email contact for service %s" % self.name) try: + title = "{} Service Check Failed: {}".format(self.name, description) email_msg = get_template("alert_email.txt").render( Context({"description":description, "service_name":self.name, @@ -87,7 +88,7 @@ def _send_alert_email(self,description): }) ) - send_mail("MOMONITOR EVENT TRIGGERED", + send_mail(title, email_msg, settings.SERVER_EMAIL, [self.email_contact,],