diff --git a/hc/api/transports.py b/hc/api/transports.py index fbcb4be3..53e0a4e6 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -161,6 +161,7 @@ class OpsGenie(HttpTransport): return self.post(url, payload) + class PagerDuty(HttpTransport): URL = "https://events.pagerduty.com/generic/2010-04-15/create_event.json" diff --git a/hc/front/forms.py b/hc/front/forms.py index 8bcb112f..daeca968 100644 --- a/hc/front/forms.py +++ b/hc/front/forms.py @@ -1,6 +1,6 @@ from django import forms from hc.front.validators import WebhookValidator -from hc.api.models import CHECK_KINDS, Channel +from hc.api.models import CHECK_KINDS class NameTagsForm(forms.Form): @@ -26,17 +26,6 @@ class TimeoutForm(forms.Form): grace = forms.IntegerField(min_value=60, max_value=2592000) -class AddChannelForm(forms.ModelForm): - - class Meta: - model = Channel - fields = ['kind', 'value'] - - def clean_value(self): - value = self.cleaned_data["value"] - return value.strip() - - class AddPdForm(forms.Form): error_css_class = "has-error" value = forms.CharField(max_length=32) diff --git a/hc/front/views.py b/hc/front/views.py index 7d4bea9c..86823174 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -14,8 +14,9 @@ from django.utils import timezone from django.utils.crypto import get_random_string from django.utils.six.moves.urllib.parse import urlencode from hc.api.decorators import uuid_or_400 -from hc.api.models import DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check, Ping -from hc.front.forms import (AddChannelForm, AddWebhookForm, NameTagsForm, +from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check, + Ping, Notification) +from hc.front.forms import (AddWebhookForm, NameTagsForm, TimeoutForm, AddUrlForm, AddPdForm, AddEmailForm, AddOpsGenieForm) from pytz import all_timezones @@ -175,8 +176,6 @@ def update_timeout(request, code): check.alert_after = check.get_alert_after() check.save() - else: - assert 0, "form is not valid! %s" % form.errors return redirect("hc-checks") @@ -218,45 +217,28 @@ def log(request, code): return HttpResponseForbidden() limit = request.team.ping_log_limit - pings = Ping.objects.filter(owner=check).order_by("-id")[:limit] - - pings = list(pings.iterator()) - # oldest-to-newest order will be more convenient for adding - # "not received" placeholders: - pings.reverse() - - # Add a dummy ping object at the end. We iterate over *pairs* of pings - # and don't want to handle a special case of a check with a single ping. - pings.append(Ping(created=timezone.now())) - - # Now go through pings, calculate time gaps, and decorate - # the pings list for convenient use in template - wrapped = [] - - early = False - for older, newer in pairwise(pings): - wrapped.append({"ping": older, "early": early}) + pings = Ping.objects.filter(owner=check).order_by("-id")[:limit + 1] + pings = list(pings) - # Fill in "missed ping" placeholders: - expected_date = older.created + check.timeout - n_blanks = 0 - while expected_date + check.grace < newer.created and n_blanks < 10: - wrapped.append({"placeholder_date": expected_date}) - expected_date = expected_date + check.timeout - n_blanks += 1 + num_pings = len(pings) + pings = pings[:limit] - # Prepare early flag for next ping to come - early = older.created + check.timeout > newer.created + check.grace + alerts = [] + if len(pings): + cutoff = pings[-1].created + alerts = Notification.objects \ + .select_related("channel") \ + .filter(owner=check, check_status="down", created__gt=cutoff) - reached_limit = len(pings) > limit + events = pings + list(alerts) + events.sort(key=lambda el: el.created, reverse=True) - wrapped.reverse() ctx = { "check": check, - "pings": wrapped, - "num_pings": len(pings), + "events": events, + "num_pings": min(num_pings, limit), "limit": limit, - "show_limit_notice": reached_limit and settings.USE_PAYMENTS + "show_limit_notice": num_pings > limit and settings.USE_PAYMENTS } return render(request, "front/log.html", ctx) diff --git a/static/css/log.css b/static/css/log.css index 7ef7ffc9..c157e40f 100644 --- a/static/css/log.css +++ b/static/css/log.css @@ -59,4 +59,8 @@ #log .hash { color: #aaa; +} + +#log .alert-info { + font-size: 12px; } \ No newline at end of file diff --git a/static/js/channels.js b/static/js/channels.js index 0417f842..3d9d4e57 100644 --- a/static/js/channels.js +++ b/static/js/channels.js @@ -32,8 +32,6 @@ $(function() { $cm.on("click", "#toggle-all", function() { var value = $(this).prop("checked"); $cm.find(".toggle").prop("checked", value); - console.log("aaa", value); - }); $(".channel-remove").click(function() { diff --git a/templates/front/log.html b/templates/front/log.html index fe100d69..77f86148 100644 --- a/templates/front/log.html +++ b/templates/front/log.html @@ -28,7 +28,7 @@ - {% if pings %} + {% if events %}
Protocol | User Agent | |||||||
---|---|---|---|---|---|---|---|---|
- {% if record.ping.n %} - #{{ record.ping.n }} - {% endif %} + #{{ event.n }} | -+ |
- {% if record.early %}
+ {% if 0 %}
early
{% endif %}
|
- {{ record.ping.remote_addr|default:"" }} + {{ event.remote_addr|default:"" }} | - {{ record.ping.scheme }} + {{ event.scheme }} | - {{ record.ping.ua }} + {{ event.ua }} | |||
- | + |
|
- - Ping expected but not received + |
+ {% if event.channel.kind == "email" %}
+ Sent email alert to {{ event.channel.value }}
+ {% elif event.channel.kind == "slack" %}
+ Sent Slack alert
+ {% if event.channel.slack_channel %}
+ to {{ event.channel.slack_channel }}
+ {% endif %}
+ {% elif event.channel.kind == "pd" %}
+ Sent alert to PagerDuty
+ {% elif event.channel.kind == "opsgenie" %}
+ Sent alert to OpsGenie
+ {% elif event.channel.kind == "hipchat" %}
+ Sent alert to HipChat
+ {% elif event.channel.kind == "webhook" %}
+ Called webhook {{ event.channel.value_down }}
+ {% else %}
+ Sent alert to {{ event.channel.kind|capfirst }}
+ {% endif %}
+ {% if event.error %}
+ + Error: {{ event.error }} + {% endif %} |