forked from GithubBackups/healthchecks
Auto-refresh current status in log page.
This commit is contained in:
parent
8b01acefe2
commit
04fede0897
@ -8,6 +8,7 @@ check_urls = [
|
|||||||
path('pause/', views.pause, name="hc-pause"),
|
path('pause/', views.pause, name="hc-pause"),
|
||||||
path('remove/', views.remove_check, name="hc-remove-check"),
|
path('remove/', views.remove_check, name="hc-remove-check"),
|
||||||
path('log/', views.log, name="hc-log"),
|
path('log/', views.log, name="hc-log"),
|
||||||
|
path('status/', views.status_single),
|
||||||
path('last_ping/', views.ping_details, name="hc-last-ping"),
|
path('last_ping/', views.ping_details, name="hc-last-ping"),
|
||||||
path('channels/<uuid:channel_code>/enabled', views.switch_channel, name="hc-switch-channel"),
|
path('channels/<uuid:channel_code>/enabled', views.switch_channel, name="hc-switch-channel"),
|
||||||
path('pings/<int:n>/', views.ping_details, name="hc-ping-details"),
|
path('pings/<int:n>/', views.ping_details, name="hc-ping-details"),
|
||||||
|
@ -32,6 +32,8 @@ import requests
|
|||||||
|
|
||||||
|
|
||||||
VALID_SORT_VALUES = ("name", "-name", "last_ping", "-last_ping", "created")
|
VALID_SORT_VALUES = ("name", "-name", "last_ping", "-last_ping", "created")
|
||||||
|
STATUS_TEXT_TMPL = get_template("front/log_status_text.html")
|
||||||
|
LAST_PING_TMPL = get_template("front/last_ping_cell.html")
|
||||||
|
|
||||||
|
|
||||||
def _tags_statuses(checks):
|
def _tags_statuses(checks):
|
||||||
@ -92,13 +94,12 @@ def status(request):
|
|||||||
checks = list(Check.objects.filter(user_id=request.team.user_id))
|
checks = list(Check.objects.filter(user_id=request.team.user_id))
|
||||||
|
|
||||||
details = []
|
details = []
|
||||||
tmpl = get_template("front/last_ping_cell.html")
|
|
||||||
for check in checks:
|
for check in checks:
|
||||||
ctx = {"check": check}
|
ctx = {"check": check}
|
||||||
details.append({
|
details.append({
|
||||||
"code": str(check.code),
|
"code": str(check.code),
|
||||||
"status": check.get_status(),
|
"status": check.get_status(),
|
||||||
"last_ping": tmpl.render(ctx)
|
"last_ping": LAST_PING_TMPL.render(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
tags_statuses, num_down = _tags_statuses(checks)
|
tags_statuses, num_down = _tags_statuses(checks)
|
||||||
@ -366,6 +367,19 @@ def log(request, code):
|
|||||||
return render(request, "front/log.html", ctx)
|
return render(request, "front/log.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def status_single(request, code):
|
||||||
|
check = get_object_or_404(Check, code=code)
|
||||||
|
if check.user_id != request.team.user.id:
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
status = check.get_status()
|
||||||
|
return JsonResponse({
|
||||||
|
"status": status,
|
||||||
|
"status_text": STATUS_TEXT_TMPL.render({"check": check})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def channels(request):
|
def channels(request):
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
42
static/js/adaptive-setinterval.js
Normal file
42
static/js/adaptive-setinterval.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
function adaptiveSetInterval(fn) {
|
||||||
|
// unconditionally run every minute
|
||||||
|
setInterval(fn, 60000);
|
||||||
|
|
||||||
|
// scheduleRun() keeps calling fn and decreasing quota
|
||||||
|
// every 3 seconds, until quota runs out.
|
||||||
|
var quota = 0;
|
||||||
|
var scheduledId = null;
|
||||||
|
function scheduleRun() {
|
||||||
|
if (quota > 0) {
|
||||||
|
quota -= 1;
|
||||||
|
clearTimeout(scheduledId);
|
||||||
|
scheduledId = setTimeout(scheduleRun, 3000);
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("visibilitychange", function() {
|
||||||
|
if (document.visibilityState == "visible") {
|
||||||
|
// tab becomes visible: reset quota
|
||||||
|
if (quota == 0) {
|
||||||
|
quota = 20;
|
||||||
|
scheduleRun();
|
||||||
|
} else {
|
||||||
|
quota = 20;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// lost visibility, clear quota
|
||||||
|
quota = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// user moves mouse: reset quota
|
||||||
|
document.addEventListener("mousemove", function() {
|
||||||
|
if (quota == 0) {
|
||||||
|
quota = 20;
|
||||||
|
scheduleRun();
|
||||||
|
} else {
|
||||||
|
quota = 20;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -135,10 +135,11 @@ $(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto-refresh
|
// Schedule refresh to run every 3s when tab is visible and user
|
||||||
|
// is active, every 60s otherwise
|
||||||
var lastStatus = {};
|
var lastStatus = {};
|
||||||
var lastPing = {};
|
var lastPing = {};
|
||||||
function refresh() {
|
adaptiveSetInterval(function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/checks/status/",
|
url: "/checks/status/",
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -171,48 +172,6 @@ $(function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// unconditionally refresh every minute
|
|
||||||
setInterval(refresh, 60000);
|
|
||||||
|
|
||||||
// scheduleRefresh() keeps calling refresh() and decreasing quota
|
|
||||||
// every 3 seconds, until quota runs out.
|
|
||||||
var quota = 0;
|
|
||||||
var scheduledId = null;
|
|
||||||
function scheduleRefresh() {
|
|
||||||
if (quota > 0) {
|
|
||||||
quota -= 1;
|
|
||||||
clearTimeout(scheduledId);
|
|
||||||
scheduledId = setTimeout(scheduleRefresh, 3000);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", function() {
|
|
||||||
if (document.visibilityState == "visible") {
|
|
||||||
// tab becomes visible: reset quota
|
|
||||||
if (quota == 0) {
|
|
||||||
quota = 20;
|
|
||||||
scheduleRefresh();
|
|
||||||
} else {
|
|
||||||
quota = 20;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// lost visibility, clear quota
|
|
||||||
quota = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// user moves mouse: reset quota
|
|
||||||
document.addEventListener("mousemove", function() {
|
|
||||||
if (quota == 0) {
|
|
||||||
quota = 20;
|
|
||||||
scheduleRefresh();
|
|
||||||
} else {
|
|
||||||
quota = 20;
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy to clipboard
|
// Copy to clipboard
|
||||||
|
@ -24,6 +24,24 @@ $(function () {
|
|||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var code = document.getElementById("edit-timeout").dataset.code;
|
||||||
|
var statusUrl = "/checks/" + code + "/status/";
|
||||||
|
var lastStatusText = "";
|
||||||
|
adaptiveSetInterval(function() {
|
||||||
|
$.ajax({
|
||||||
|
url: statusUrl,
|
||||||
|
dataType: "json",
|
||||||
|
timeout: 2000,
|
||||||
|
success: function(data) {
|
||||||
|
if (data.status_text == lastStatusText) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastStatusText = data.status_text;
|
||||||
|
$("#log-status-icon").attr("class", "status icon-" + data.status);
|
||||||
|
$("#log-status-text").text(data.status_text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Copy to clipboard
|
// Copy to clipboard
|
||||||
var clipboard = new Clipboard('button.copy-btn');
|
var clipboard = new Clipboard('button.copy-btn');
|
||||||
|
@ -46,26 +46,14 @@
|
|||||||
<div class="details-block">
|
<div class="details-block">
|
||||||
<h2>Current Status</h2>
|
<h2>Current Status</h2>
|
||||||
<table>
|
<table>
|
||||||
{% with check.get_status as status %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span class="status icon-{{ status }}"></span>
|
<span id="log-status-icon" class="status icon-{{ check.get_status }}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td id="log-status-text">
|
||||||
{% if status == "down" %}
|
{% include "front/log_status_text.html" %}
|
||||||
This check is down. Last ping was {{ check.last_ping|naturaltime }}.
|
|
||||||
{% elif status == "up" %}
|
|
||||||
This check is up. Last ping was {{ check.last_ping|naturaltime }}.
|
|
||||||
{% elif status == "grace" %}
|
|
||||||
This check is late. Last ping was {{ check.last_ping|naturaltime }}.
|
|
||||||
{% elif status == "paused" %}
|
|
||||||
This check is paused.
|
|
||||||
{% elif status == "new" %}
|
|
||||||
This check has never received a ping.
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endwith %}
|
|
||||||
</table>
|
</table>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<form action="{% url 'hc-pause' check.code %}" method="post">
|
<form action="{% url 'hc-pause' check.code %}" method="post">
|
||||||
@ -299,8 +287,10 @@
|
|||||||
<script src="{% static 'js/clipboard.min.js' %}"></script>
|
<script src="{% static 'js/clipboard.min.js' %}"></script>
|
||||||
<script src="{% static 'js/selectize.min.js' %}"></script>
|
<script src="{% static 'js/selectize.min.js' %}"></script>
|
||||||
<script src="{% static 'js/nouislider.min.js' %}"></script>
|
<script src="{% static 'js/nouislider.min.js' %}"></script>
|
||||||
|
<script src="{% static 'js/snippet-copy.js' %}"></script>
|
||||||
<script src="{% static 'js/moment.min.js' %}"></script>
|
<script src="{% static 'js/moment.min.js' %}"></script>
|
||||||
<script src="{% static 'js/update-timeout-modal.js' %}"></script>
|
<script src="{% static 'js/update-timeout-modal.js' %}"></script>
|
||||||
|
<script src="{% static 'js/adaptive-setinterval.js' %}"></script>
|
||||||
<script src="{% static 'js/log.js' %}"></script>
|
<script src="{% static 'js/log.js' %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
14
templates/front/log_status_text.html
Normal file
14
templates/front/log_status_text.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{% load humanize %}
|
||||||
|
{% with check.get_status as status %}
|
||||||
|
{% if status == "down" %}
|
||||||
|
This check is down. Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
{% elif status == "up" %}
|
||||||
|
This check is up. Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
{% elif status == "grace" %}
|
||||||
|
This check is late. Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
{% elif status == "paused" %}
|
||||||
|
This check is paused.
|
||||||
|
{% elif status == "new" %}
|
||||||
|
This check has never received a ping.
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
@ -79,8 +79,8 @@
|
|||||||
<script src="{% static 'js/selectize.min.js' %}"></script>
|
<script src="{% static 'js/selectize.min.js' %}"></script>
|
||||||
<script src="{% static 'js/nouislider.min.js' %}"></script>
|
<script src="{% static 'js/nouislider.min.js' %}"></script>
|
||||||
<script src="{% static 'js/clipboard.min.js' %}"></script>
|
<script src="{% static 'js/clipboard.min.js' %}"></script>
|
||||||
<script src="{% static 'js/snippet-copy.js' %}"></script>
|
|
||||||
<script src="{% static 'js/update-timeout-modal.js' %}"></script>
|
<script src="{% static 'js/update-timeout-modal.js' %}"></script>
|
||||||
|
<script src="{% static 'js/adaptive-setinterval.js' %}"></script>
|
||||||
<script src="{% static 'js/checks.js' %}"></script>
|
<script src="{% static 'js/checks.js' %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user