mirror of
https://github.com/healthchecks/healthchecks.git
synced 2025-04-13 08:31:44 +00:00

In the "Details" and "Log" pages Healthchecks displays a list of events (incoming pings and sent alerts). At the top of the events list is a two- or three-way selector for selecting the timezone for formatting event dates and times. The selector options are "UTC", check's configured timezone, and "Browser's time zone". The "Browser's time zone" used to be default, initial selection for all checks. With this change, for checks that use cron schedule, the default selected timezone will be the check's configured timezone. The "Browser's time zone" option is of course still there and the user can switch to it to see dates and times in their local time. Rationale: I semi-regularly get support requests about unexpected or missing alerts, where the problem boil downs to a timezone mismatch between the client and the Healthchecks server. Sometimes the confusion seems to be caused by the user seeing ping arrival times in their local time zone, comparing them to their cron expression, and not realizing their server may be using a different timezone. By switching the default display timezone to the check's configured timezone, I hope users will be more likely to notice discrepancies between ping arrival times, the cron schedule, and their local clock. For checks using simple schedules (timeout and grace), we still default to browser's timezone for display.
123 lines
3.7 KiB
JavaScript
123 lines
3.7 KiB
JavaScript
$(function () {
|
|
var BIG_LABEL = 1;
|
|
var SMALL_LABEL = 2;
|
|
var PIP = 0;
|
|
var NO_PIP = -1;
|
|
|
|
var slider = document.getElementById("log-slider");
|
|
var smin = parseInt(slider.dataset.min);
|
|
var smax = parseInt(slider.dataset.max);
|
|
var pixelsPerSecond = slider.clientWidth / (smax - smin);
|
|
var pixelsPerHour = pixelsPerSecond * 3600;
|
|
var pixelsPerDay = pixelsPerHour * 24;
|
|
var dayGap = Math.round(0.5 + 80 / pixelsPerDay);
|
|
|
|
// Look up the active tz switch to determine the initial display timezone:
|
|
var dateFormat = $(".active", "#format-switcher").data("format");
|
|
function fromUnix(timestamp) {
|
|
var dt = moment.unix(timestamp);
|
|
dateFormat == "local" ? dt.local() : dt.tz(dateFormat);
|
|
return dt;
|
|
}
|
|
|
|
function filterPips(value, type) {
|
|
var m = fromUnix(value);
|
|
if (m.minute() != 0)
|
|
return NO_PIP;
|
|
|
|
// Date labels on every day
|
|
if (pixelsPerDay > 60 && m.hour() == 0)
|
|
return BIG_LABEL;
|
|
|
|
// Date labels every "dayGap" days
|
|
if (m.hour() == 0 && m.dayOfYear() % dayGap == 0)
|
|
return BIG_LABEL;
|
|
|
|
// Hour labels on every hour:
|
|
if (pixelsPerHour > 40)
|
|
return SMALL_LABEL;
|
|
|
|
// Hour labels every 3 hours:
|
|
if (pixelsPerHour > 15 && m.hour() % 3 == 0)
|
|
return SMALL_LABEL;
|
|
|
|
// Hour labels every 6 hours:
|
|
if (pixelsPerHour > 5 && m.hour() % 6 == 0)
|
|
return SMALL_LABEL;
|
|
|
|
// Pip on every hour
|
|
if (pixelsPerHour > 5)
|
|
return PIP;
|
|
|
|
// Pip on every day
|
|
if (pixelsPerDay > 10 && m.hour() == 0)
|
|
return PIP;
|
|
|
|
return NO_PIP;
|
|
}
|
|
|
|
function fmt(ts) {
|
|
var pipType = filterPips(ts);
|
|
return fromUnix(ts).format(pipType == 2 ? "HH:mm" : "MMM D");
|
|
}
|
|
|
|
noUiSlider.create(slider, {
|
|
start: [parseInt(slider.dataset.start), parseInt(slider.dataset.end)],
|
|
range: {'min': smin, 'max': smax},
|
|
connect: true,
|
|
step: 3600,
|
|
pips: {
|
|
mode: "steps",
|
|
density: 3,
|
|
filter: filterPips,
|
|
format: {
|
|
to: fmt,
|
|
from: function() {}
|
|
}
|
|
}
|
|
});
|
|
|
|
function updateSliderPreview() {
|
|
var values = slider.noUiSlider.get();
|
|
$("#slider-from-formatted").text(fromUnix(values[0]).format("MMMM D, HH:mm"));
|
|
$("#slider-to-formatted").text(fromUnix(values[1]).format("MMMM D, HH:mm"));
|
|
}
|
|
|
|
updateSliderPreview();
|
|
slider.noUiSlider.on("slide", updateSliderPreview);
|
|
|
|
slider.noUiSlider.on("change", function(a, b, value) {
|
|
$("#seek-start").val(Math.round(value[0]));
|
|
$("#seek-end").val(Math.round(value[1]));
|
|
$("#seek-form").submit();
|
|
});
|
|
|
|
$("#log tr.ok").on("click", function() {
|
|
var n = $("td", this).first().text();
|
|
var tmpl = $("#log").data("url").slice(0, -2);
|
|
loadPingDetails(tmpl + n + "/");
|
|
return false;
|
|
});
|
|
|
|
function switchDateFormat(format) {
|
|
dateFormat = format;
|
|
slider.noUiSlider.updateOptions({}, true);
|
|
updateSliderPreview();
|
|
|
|
document.querySelectorAll("#log tr").forEach(function(row) {
|
|
var dt = fromUnix(row.dataset.dt);
|
|
row.children[1].textContent = dt.format("MMM D");
|
|
row.children[2].textContent = dt.format("HH:mm");
|
|
})
|
|
}
|
|
|
|
$("#format-switcher").click(function(ev) {
|
|
var format = ev.target.dataset.format;
|
|
switchDateFormat(format);
|
|
});
|
|
|
|
switchDateFormat(dateFormat);
|
|
// The table is initially hidden to avoid flickering as we convert dates.
|
|
// Once it's ready, set it to visible:
|
|
$("#log").css("visibility", "visible");
|
|
});
|