|
import { Http } from "./Http.js";
|
|
|
|
class ServiceMonitor {
|
|
constructor() {
|
|
this.pollInterval = 5000;
|
|
}
|
|
|
|
start() {
|
|
this.pollServices();
|
|
setInterval(() => this.pollServices(), this.pollInterval);
|
|
}
|
|
|
|
formatDate(isoStr, includeTime) {
|
|
if (!isoStr) return "-";
|
|
try {
|
|
const d = new Date(isoStr);
|
|
if (isNaN(d.getTime())) return isoStr.slice(0, 19);
|
|
const dd = String(d.getDate()).padStart(2, "0");
|
|
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
const yyyy = d.getFullYear();
|
|
if (includeTime) {
|
|
const hh = String(d.getHours()).padStart(2, "0");
|
|
const mi = String(d.getMinutes()).padStart(2, "0");
|
|
return `${dd}/${mm}/${yyyy} ${hh}:${mi}`;
|
|
}
|
|
return `${dd}/${mm}/${yyyy}`;
|
|
} catch {
|
|
return isoStr.slice(0, 19);
|
|
}
|
|
}
|
|
|
|
async pollServices() {
|
|
try {
|
|
const data = await Http.getJson("/admin/services/data");
|
|
const container = document.getElementById("services-list");
|
|
if (!container) return;
|
|
for (const svc of data.services) {
|
|
const card = container.querySelector(`.service-card[data-service="${svc.name}"]`);
|
|
if (!card) continue;
|
|
const statusEl = card.querySelector(".service-status");
|
|
if (statusEl) {
|
|
statusEl.textContent = svc.status;
|
|
statusEl.className = "service-status " + svc.status;
|
|
}
|
|
const metaItems = card.querySelectorAll(".meta-item");
|
|
if (metaItems.length >= 3) {
|
|
metaItems[0].textContent = "Uptime: " + (svc.uptime || "-");
|
|
metaItems[1].textContent = "Last run: " + this.formatDate(svc.last_run, true);
|
|
metaItems[2].textContent = "Next run: " + this.formatDate(svc.next_run, true);
|
|
}
|
|
const logPre = card.querySelector(".log-output");
|
|
if (logPre) {
|
|
logPre.textContent = (svc.log_buffer || []).map((l) => l + "\n").join("") || "No log entries yet.\n";
|
|
}
|
|
}
|
|
} catch {
|
|
// silently ignore poll errors
|
|
}
|
|
}
|
|
}
|
|
window.ServiceMonitor = ServiceMonitor;
|