diff --git a/common/static/js/momonitoring.js b/common/static/js/momonitoring.js
index 392a387..b5d3547 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$) {
if(typeof(container$)==='undefined') container$ = $('body');
@@ -239,6 +299,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/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,],
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)
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/codeservicecheck.html b/main/templates/main/modal_forms/codeservicecheck.html
index 589d4e3..4b44014 100644
--- a/main/templates/main/modal_forms/codeservicecheck.html
+++ b/main/templates/main/modal_forms/codeservicecheck.html
@@ -9,12 +9,17 @@
{{form.name}}
Description
{{form.description}}
-
-
- {{form.silenced}} Silenced
Code File
{{form.code_file}}
+
diff --git a/main/templates/main/modal_forms/compareservicecheck.html b/main/templates/main/modal_forms/compareservicecheck.html
index f7c2571..37c5f21 100644
--- a/main/templates/main/modal_forms/compareservicecheck.html
+++ b/main/templates/main/modal_forms/compareservicecheck.html
@@ -9,9 +9,6 @@
{{form.name}}
Description
{{form.description}}
-
-
- {{form.silenced}} Silenced
URL Endpoint
{{form.endpoint}}
Serialization
@@ -21,6 +18,14 @@
Comparator
{{form.comparator}} {{form.compared_value}}
+
diff --git a/main/templates/main/modal_forms/sensuservicecheck.html b/main/templates/main/modal_forms/sensuservicecheck.html
index fd4949d..2e2e760 100644
--- a/main/templates/main/modal_forms/sensuservicecheck.html
+++ b/main/templates/main/modal_forms/sensuservicecheck.html
@@ -9,12 +9,17 @@
{{form.name}}
Description (optional)
{{form.description}}
-
-
- {{form.silenced}} Silenced
Sensu Check Name
{{form.sensu_check_name}}
+
diff --git a/main/templates/main/modal_forms/simpleservicecheck.html b/main/templates/main/modal_forms/simpleservicecheck.html
index 445bd3f..9689f8d 100644
--- a/main/templates/main/modal_forms/simpleservicecheck.html
+++ b/main/templates/main/modal_forms/simpleservicecheck.html
@@ -9,14 +9,19 @@
{{form.name}}
Description (optional)
{{form.description}}
-
-
- {{form.silenced}} Silenced
URL Endpoint
{{form.endpoint}}
Timeout (ms) (optional)
{{form.timeout}}
+
diff --git a/main/templates/main/modal_forms/umpireservicecheck.html b/main/templates/main/modal_forms/umpireservicecheck.html
index 9ab2967..42eacb2 100644
--- a/main/templates/main/modal_forms/umpireservicecheck.html
+++ b/main/templates/main/modal_forms/umpireservicecheck.html
@@ -13,31 +13,37 @@
{{form.umpire_check_type}}
Umpire Range Type
{{form.umpire_range_type}}
-
-
- {{form.silenced}} Silenced
Umpire Metric
{{form.umpire_metric}}
+
+
+
Silenced or Not Silenced?
+
Silenced until (timestamp)
+ {{form.silenced_until}}
+
UnSilence
+
Silence for hours
+
Silence forever
+
-----
- Umpire Min
- {{form.umpire_min}}
- Umpire Max
- {{form.umpire_max}}
+ Umpire Min
+ {{form.umpire_min}}
+ Umpire Max
+ {{form.umpire_max}}
- Percent Error (from guessed value)
- {{form.umpire_percent_error}}
- Error range will be computed over time based on past history
+ Percent Error (from guessed value)
+ {{form.umpire_percent_error}}
+ Error range will be computed over time based on past history
- Umpire Range
- {{form.umpire_range}}
+ 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
diff --git a/main/templates/main/tables/codeservicecheck.html b/main/templates/main/tables/codeservicecheck.html
index 69d227c..c6ae28e 100644
--- a/main/templates/main/tables/codeservicecheck.html
+++ b/main/templates/main/tables/codeservicecheck.html
@@ -19,9 +19,9 @@ Code Checks
{% if service_checks.count %}
{% for check in service_checks|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/compareservicecheck.html b/main/templates/main/tables/compareservicecheck.html
index 437f64b..26029df 100644
--- a/main/templates/main/tables/compareservicecheck.html
+++ b/main/templates/main/tables/compareservicecheck.html
@@ -22,10 +22,10 @@ Compare Checks
{% if service_checks.count %}
{% for check in service_checks.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/sensuservicecheck.html b/main/templates/main/tables/sensuservicecheck.html
index f2e4e3c..cc21b88 100644
--- a/main/templates/main/tables/sensuservicecheck.html
+++ b/main/templates/main/tables/sensuservicecheck.html
@@ -20,9 +20,9 @@ Sensu Checks
{% if service_checks.count %}
{% for check in service_checks.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/simpleservicecheck.html b/main/templates/main/tables/simpleservicecheck.html
index cf7f818..144725a 100644
--- a/main/templates/main/tables/simpleservicecheck.html
+++ b/main/templates/main/tables/simpleservicecheck.html
@@ -19,9 +19,9 @@ Simple Checks
{% if service_checks.count %}
{% for check in service_checks|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/umpireservicecheck.html b/main/templates/main/tables/umpireservicecheck.html
index 69f7dc7..4773bb3 100644
--- a/main/templates/main/tables/umpireservicecheck.html
+++ b/main/templates/main/tables/umpireservicecheck.html
@@ -19,10 +19,10 @@ Umpire Checks
{% if service_checks.count %}
{% for check in service_checks|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/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('')
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 %}
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}),
)