This commit is contained in:
Mateusz Gruszczyński committed 2026-10-15 09:37:47 +02:00
1 parent bbfa8cbc3f
commit 2ccc598b12
49 files changed
+4771 -639

No files matched your search

+61 -2
View File
@@ -392,11 +392,70 @@
item.append(el("span", t(key), "small-label"), el("b", value));
details.append(item);
}
box.append(details); return box;
const live = el("details", undefined, "www-service-panel");
const summary = el("summary", t("webLiveMetrics")); live.append(summary);
const panel = el("div", undefined, "www-service-live"); panel.dataset.webLiveId = service.id;
const figures = el("div", undefined, "www-service-values");
for (const [field, key] of [
["requests", "webLiveRequests"], ["rate", "webLiveRate"],
["errors", "webLiveErrors"], ["latency", "webLiveLatency"],
["php", "webLivePhpCapacity"], ["bytes", "webLiveBytes"]]) {
const item = el("div");
const name = el("small", t(key));
name.dataset.i18n = key;
const value = el("strong", "-"); value.dataset.webLiveField = field;
item.append(name, value); figures.append(item);
}
const chart = document.createElementNS("http://www.w3.org/2000/svg", "svg");
chart.setAttribute("viewBox", "0 0 300 60"); chart.setAttribute("role", "img");
chart.setAttribute("aria-label", t("webLiveRate"));
const line = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
line.setAttribute("points", "0,55 300,55"); chart.append(line);
const split = el("p", "-", "www-service-split"); split.dataset.webLiveField = "split";
panel.append(figures, chart, split); live.append(panel);
live.addEventListener("toggle", () => { if (live.open && latestStatus) renderLive(latestStatus, false); });
box.append(details, live); return box;
});
$("web-service-list").replaceChildren(...(cards.length ? cards : [el("p", t(query ? "webServiceSearchEmpty" : "webServiceEmpty"), "fine")]));
}
const serviceHistory = new Map();
const serviceLast = new Map();
function renderLive(status, record = true) {
if (currentPanel !== "web-server") return;
const services = status?.web_server_metrics || {};
for (const panel of document.querySelectorAll("#web-service-list [data-web-live-id]")) {
if (!panel.closest("details")?.open) continue;
const id = panel.dataset.webLiveId, values = services[id], web = values?.web;
const lookup = key => panel.querySelector(`[data-web-live-field="${key}"]`);
const set = (key, value) => { const node = lookup(key); if (node) node.textContent = value; };
if (!web) { for (const key of ["requests", "rate", "errors", "latency", "php", "bytes", "split"]) set(key, "-"); continue; }
const n = value => value == null || !Number.isFinite(Number(value)) ? 0 : Number(value);
const total = n(web.requests), php = values.php, last = serviceLast.get(id);
const sample = rustProxyRateSampling.difference(record ? last : null,
[total, n(web.response_headers_us), n(web.status_5xx)], performance.now(),
rustProxyRateSampling.cadence("overview_seconds"));
if (record) serviceLast.set(id, sample.next);
const deltas = record ? sample.deltas : null;
const rate = deltas ? deltas[0] / sample.seconds : null;
const previous = serviceHistory.get(id) || [];
if (record) { previous.push(rate); window.rustProxyOverviewSamples.trim(previous); serviceHistory.set(id, previous); }
const peak = Math.max(1, ...previous.filter(x => x != null));
const points = previous.map((value, i) => `${300 * i / Math.max(1, previous.length - 1)},${55 - (value || 0) / peak * 50}`).join(" ");
panel.querySelector("polyline")?.setAttribute("points", points || "0,55 300,55");
set("requests", fmt(total)); set("rate", rate == null ? "-" : `${fmt(rate, 1)}/s`);
set("errors", fmt(n(web.status_5xx)));
set("latency", deltas?.[0] > 0 ? `${fmt(deltas[1] / deltas[0] / 1000, 1)} ms` : "-");
set("php", php ? `${fmt(n(php.capacity_used))} / ${fmt(n(php.capacity_limit))}` : t("webLiveNoPhp"));
set("bytes", fmtBytes(n(web.response_bytes)));
set("split", `${t("webLiveKinds")}: ${fmt(n(web.static_requests))} / ${fmt(n(web.php_requests))} / ${fmt(n(web.other_requests))}`);
}
}
window.rustProxyOverviewSamples.onChange(() => {
for (const history of serviceHistory.values()) window.rustProxyOverviewSamples.trim(history);
if (latestStatus && currentPanel === "web-server") renderLive(latestStatus, false);
});
form.addEventListener("submit", async event => {
event.preventDefault(); if (!envelope || busy) return;
const invalid = [...form.elements].find(input => input.willValidate && !input.checkValidity()); if (invalid) { activateTab(invalid.closest("[data-web-service-page]")?.dataset.webServicePage || "general"); invalid.reportValidity(); return; }
@@ -491,6 +550,6 @@
$("web-service-search").addEventListener("input", render);
dialog.addEventListener("cancel", event => { event.preventDefault(); closeEditor(); });
window.rustProxyDrafts.register("web-server", { labelKey: "webServer", isOpen: () => dialog.open, isDirty: () => dirty, suspend: suspendDraft, restore: restoreDraft, close: clearEditor });
window.rustProxyWebServer = { render, reset: clearEditor };
window.rustProxyWebServer = { render, renderLive, reset() { clearEditor(); serviceHistory.clear(); serviceLast.clear(); } };
if (envelope) render();
})();