forked from GithubBackups/healthchecks
Log page now lists sent notifications. Slack notification handles simple/cron check kinds.
This commit is contained in:
parent
5a4c3ce8ea
commit
fdc1bfcd57
@ -161,6 +161,7 @@ class OpsGenie(HttpTransport):
|
|||||||
|
|
||||||
return self.post(url, payload)
|
return self.post(url, payload)
|
||||||
|
|
||||||
|
|
||||||
class PagerDuty(HttpTransport):
|
class PagerDuty(HttpTransport):
|
||||||
URL = "https://events.pagerduty.com/generic/2010-04-15/create_event.json"
|
URL = "https://events.pagerduty.com/generic/2010-04-15/create_event.json"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from hc.front.validators import WebhookValidator
|
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):
|
class NameTagsForm(forms.Form):
|
||||||
@ -26,17 +26,6 @@ class TimeoutForm(forms.Form):
|
|||||||
grace = forms.IntegerField(min_value=60, max_value=2592000)
|
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):
|
class AddPdForm(forms.Form):
|
||||||
error_css_class = "has-error"
|
error_css_class = "has-error"
|
||||||
value = forms.CharField(max_length=32)
|
value = forms.CharField(max_length=32)
|
||||||
|
@ -14,8 +14,9 @@ from django.utils import timezone
|
|||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.six.moves.urllib.parse import urlencode
|
from django.utils.six.moves.urllib.parse import urlencode
|
||||||
from hc.api.decorators import uuid_or_400
|
from hc.api.decorators import uuid_or_400
|
||||||
from hc.api.models import DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check, Ping
|
from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
|
||||||
from hc.front.forms import (AddChannelForm, AddWebhookForm, NameTagsForm,
|
Ping, Notification)
|
||||||
|
from hc.front.forms import (AddWebhookForm, NameTagsForm,
|
||||||
TimeoutForm, AddUrlForm, AddPdForm, AddEmailForm,
|
TimeoutForm, AddUrlForm, AddPdForm, AddEmailForm,
|
||||||
AddOpsGenieForm)
|
AddOpsGenieForm)
|
||||||
from pytz import all_timezones
|
from pytz import all_timezones
|
||||||
@ -175,8 +176,6 @@ def update_timeout(request, code):
|
|||||||
check.alert_after = check.get_alert_after()
|
check.alert_after = check.get_alert_after()
|
||||||
|
|
||||||
check.save()
|
check.save()
|
||||||
else:
|
|
||||||
assert 0, "form is not valid! %s" % form.errors
|
|
||||||
|
|
||||||
return redirect("hc-checks")
|
return redirect("hc-checks")
|
||||||
|
|
||||||
@ -218,45 +217,28 @@ def log(request, code):
|
|||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
limit = request.team.ping_log_limit
|
limit = request.team.ping_log_limit
|
||||||
pings = Ping.objects.filter(owner=check).order_by("-id")[:limit]
|
pings = Ping.objects.filter(owner=check).order_by("-id")[:limit + 1]
|
||||||
|
pings = list(pings)
|
||||||
|
|
||||||
pings = list(pings.iterator())
|
num_pings = len(pings)
|
||||||
# oldest-to-newest order will be more convenient for adding
|
pings = pings[:limit]
|
||||||
# "not received" placeholders:
|
|
||||||
pings.reverse()
|
|
||||||
|
|
||||||
# Add a dummy ping object at the end. We iterate over *pairs* of pings
|
alerts = []
|
||||||
# and don't want to handle a special case of a check with a single ping.
|
if len(pings):
|
||||||
pings.append(Ping(created=timezone.now()))
|
cutoff = pings[-1].created
|
||||||
|
alerts = Notification.objects \
|
||||||
|
.select_related("channel") \
|
||||||
|
.filter(owner=check, check_status="down", created__gt=cutoff)
|
||||||
|
|
||||||
# Now go through pings, calculate time gaps, and decorate
|
events = pings + list(alerts)
|
||||||
# the pings list for convenient use in template
|
events.sort(key=lambda el: el.created, reverse=True)
|
||||||
wrapped = []
|
|
||||||
|
|
||||||
early = False
|
|
||||||
for older, newer in pairwise(pings):
|
|
||||||
wrapped.append({"ping": older, "early": early})
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Prepare early flag for next ping to come
|
|
||||||
early = older.created + check.timeout > newer.created + check.grace
|
|
||||||
|
|
||||||
reached_limit = len(pings) > limit
|
|
||||||
|
|
||||||
wrapped.reverse()
|
|
||||||
ctx = {
|
ctx = {
|
||||||
"check": check,
|
"check": check,
|
||||||
"pings": wrapped,
|
"events": events,
|
||||||
"num_pings": len(pings),
|
"num_pings": min(num_pings, limit),
|
||||||
"limit": 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)
|
return render(request, "front/log.html", ctx)
|
||||||
|
@ -60,3 +60,7 @@
|
|||||||
#log .hash {
|
#log .hash {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#log .alert-info {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
@ -32,8 +32,6 @@ $(function() {
|
|||||||
$cm.on("click", "#toggle-all", function() {
|
$cm.on("click", "#toggle-all", function() {
|
||||||
var value = $(this).prop("checked");
|
var value = $(this).prop("checked");
|
||||||
$cm.find(".toggle").prop("checked", value);
|
$cm.find(".toggle").prop("checked", value);
|
||||||
console.log("aaa", value);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".channel-remove").click(function() {
|
$(".channel-remove").click(function() {
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
{% if pings %}
|
{% if events %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table" id="log">
|
<table class="table" id="log">
|
||||||
<tr>
|
<tr>
|
||||||
@ -41,48 +41,67 @@
|
|||||||
<th class="protocol">Protocol</th>
|
<th class="protocol">Protocol</th>
|
||||||
<th class="ua">User Agent</th>
|
<th class="ua">User Agent</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for record in pings %}
|
{% for event in events %}
|
||||||
{% if record.ping %}
|
{% if event.n %}
|
||||||
<tr class="ok {% if record.early %} early {% endif %}">
|
<tr class="ok {% if record.early %} early {% endif %}">
|
||||||
<td class="n-cell">
|
<td class="n-cell">
|
||||||
{% if record.ping.n %}
|
<span class="hash">#</span>{{ event.n }}
|
||||||
<span class="hash">#</span>{{ record.ping.n }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
<td class="datetime" data-raw="{{ record.ping.created.isoformat }}">
|
<td class="datetime" data-raw="{{ event.created.isoformat }}">
|
||||||
<div>
|
<div>
|
||||||
<span class="date"></span>
|
<span class="date"></span>
|
||||||
<span class="time"></span>
|
<span class="time"></span>
|
||||||
{% if record.early %}
|
{% if 0 %}
|
||||||
<span class="label label-tag">early</span>
|
<span class="label label-tag">early</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="ip">
|
<td class="ip">
|
||||||
{{ record.ping.remote_addr|default:"" }}
|
{{ event.remote_addr|default:"" }}
|
||||||
</td>
|
</td>
|
||||||
<td class="protocol">
|
<td class="protocol">
|
||||||
{{ record.ping.scheme }}
|
{{ event.scheme }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="ua">
|
<td class="ua">
|
||||||
{{ record.ping.ua }}
|
{{ event.ua }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if record.placeholder_date %}
|
{% if event.check_status %}
|
||||||
<tr class="missing">
|
<tr class="missing">
|
||||||
<td class="n-cell">
|
<td class="n-cell">
|
||||||
<span class="icon-missing"></span>
|
<span class="icon-missing"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="datetime" data-raw="{{ record.placeholder_date.isoformat }}">
|
<td class="datetime" data-raw="{{ event.created.isoformat }}">
|
||||||
<div>
|
<div>
|
||||||
<span class="date"></span>
|
<span class="date"></span>
|
||||||
<span class="time"></span>
|
<span class="time"></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="3">
|
<td colspan="3" class="alert-info">
|
||||||
<small>Ping expected but not received</small>
|
{% 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 %}
|
||||||
|
<br />
|
||||||
|
<strong>Error: {{ event.error }}</strong>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% load hc_extras humanize %}
|
{% load hc_extras humanize %}
|
||||||
|
|
||||||
Expecting to receive a ping every {{ check.timeout|hc_duration }}.
|
{% if check.kind == "simple" %}Expecting to receive a ping every {{ check.timeout|hc_duration }}.{% endif %}
|
||||||
Last ping was {{ check.last_ping|naturaltime }}.
|
Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
@ -13,31 +13,37 @@
|
|||||||
"mrkdwn_in": ["fields"],
|
"mrkdwn_in": ["fields"],
|
||||||
"text": "“{{ check.name_then_code|escapejs }}” is {{ check.status|upper }}.",
|
"text": "“{{ check.name_then_code|escapejs }}” is {{ check.status|upper }}.",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{% if check.kind == "simple" %}
|
||||||
"title": "Period",
|
{"title": "Period",
|
||||||
"value": "{{ check.timeout|hc_duration }}",
|
"value": "{{ check.timeout|hc_duration }}",
|
||||||
"short": true
|
"short": true
|
||||||
},
|
},
|
||||||
{
|
{% elif check.kind == "cron" %}
|
||||||
"title": "Last Ping",
|
{"title": "Schedule",
|
||||||
{% if check.last_ping %}
|
"value": "{{ check.schedule }}",
|
||||||
"value": "{{ check.last_ping|naturaltime }}",
|
"short": true
|
||||||
{% else %}
|
},
|
||||||
"value": "Never",
|
|
||||||
{% endif %}
|
|
||||||
"short": true
|
|
||||||
},
|
|
||||||
{% if check.tags_list %}
|
|
||||||
{
|
|
||||||
"title": "Tags",
|
|
||||||
"value": "{% for tag in check.tags_list %}`{{ tag|escapejs }}` {% endfor %}",
|
|
||||||
"short": true
|
|
||||||
},
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{
|
|
||||||
"title": "Total Pings",
|
{"title": "Last Ping",
|
||||||
"value": "{{ check.n_pings }}",
|
{% if check.last_ping %}
|
||||||
"short": true
|
"value": "{{ check.last_ping|naturaltime }}",
|
||||||
|
{% else %}
|
||||||
|
"value": "Never",
|
||||||
|
{% endif %}
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{% if check.tags_list %}
|
||||||
|
{"title": "Tags",
|
||||||
|
"value": "{% for tag in check.tags_list %}`{{ tag|escapejs }}` {% endfor %}",
|
||||||
|
"short": true
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{"title": "Total Pings",
|
||||||
|
"value": "{{ check.n_pings }}",
|
||||||
|
"short": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user