This commit is contained in:
Mateusz Gruszczyński committed 2026-11-08 06:20:03 +01:00
1 parent 5cb63f542c
commit 17e314e159
27 files changed
+1017 -291

No files matched your search

+33 -3
View File
@@ -282,6 +282,15 @@ function svgNode(tag, attrs = {}) {
function setChartText(node, value) {
const text = String(value);
// Controls decorated by the optional SVG icons hold [svg.ui-icon, text]; keep the icon
// and update only the text node so periodic refreshes do not rebuild the button.
const icon = node.querySelector(":scope > svg.ui-icon");
if (icon) {
const last = node.lastChild;
if (last?.nodeType === 3) { if (last.data !== text) last.data = text; }
else node.append(text);
return;
}
if (node.firstChild?.nodeType === 3 && node.firstChild === node.lastChild) {
if (node.firstChild.data !== text) node.firstChild.data = text;
} else if (node.textContent !== text) {
@@ -346,9 +355,12 @@ function renderNetworkInterfaceCharts(interfaces, appendSample) {
setChartText(row.querySelector(".network-interface-hide"), t("hideMetric"));
row.querySelector(".network-rx-line").setAttribute("points", sparklinePoints(history.rx, 300, 60, 5, peak) || "0,55 300,55");
row.querySelector(".network-tx-line").setAttribute("points", sparklinePoints(history.tx, 300, 60, 5, peak) || "0,55 300,55");
window.rustProxyChartScale.axes(row.querySelector("svg"), peak, "bytes/s", history.rx.length,
// The Hide button precedes the chart and may carry an injected svg.ui-icon:
// address the chart explicitly so axes/labels never attach to the icon.
const chart = row.querySelector("svg:not(.ui-icon)");
window.rustProxyChartScale.axes(chart, peak, "bytes/s", history.rx.length,
{ top: 5 / 60, bottom: 55 / 60 });
row.querySelector("svg").setAttribute("aria-label", `${name} ${t("networkInterfacesHistory")}`);
chart.setAttribute("aria-label", `${name} ${t("networkInterfacesHistory")}`);
children.push(row);
}
const hidden = current.filter(item => item?.name && hiddenNetworkInterfaces.has(item.name));
@@ -395,15 +407,32 @@ function cacheOutcomeMix(totals) {
const counts = [hits, misses, bypasses, requests - cacheTotal];
return { counts, percentages: counts.map(value => value / requests * 100), requests };
}
// Percent labels live inside the bar segments; a label that does not fit is hidden
// (the legend below always carries the exact value).
function fitCacheMixLabels() {
const bar = $("cache-mix-bar");
if (!bar) return;
bar.querySelectorAll(":scope > span").forEach(segment => {
segment.classList.remove("is-tight");
segment.classList.toggle("is-tight", segment.textContent !== "" && segment.scrollWidth > segment.clientWidth);
});
if (!bar.dataset.fitObserved && typeof ResizeObserver === "function") {
bar.dataset.fitObserved = "1";
new ResizeObserver(() => fitCacheMixLabels()).observe(bar);
}
}
function renderCacheMix(mix, totalRequests) {
const names = ["hit", "miss", "bypass", "other"];
const unavailable = t(totalRequests === 0 ? "cacheMixWaiting" : "cacheMixInvalid");
names.forEach((name, i) => {
const pct = mix ? mix.percentages[i] : 0;
$(`cache-mix-${name}`).style.width = `${pct}%`;
const segment = $(`cache-mix-${name}`);
segment.style.width = `${pct}%`;
segment.textContent = mix && pct > 0 ? `${fmt(pct, pct < 10 ? 1 : 0)}%` : "";
$(`cache-mix-${name}-count`).textContent = mix ? fmt(mix.counts[i]) : "-";
$(`cache-mix-${name}-percent`).textContent = mix ? `${fmt(pct, 1)}%` : "-";
});
fitCacheMixLabels();
$("cache-mix-headline").textContent = mix ? `${fmt(mix.percentages[0], 1)}% HIT` : "-";
const caption = $("cache-mix-caption");
const validTotal = Number.isSafeInteger(totalRequests) && totalRequests >= 0;
@@ -424,6 +453,7 @@ function renderCacheMix(mix, totalRequests) {
function renderDiagnostics(status, appendSample = true, systemSample = appendSample) {
const d = status.system || {}, live = status.live_system || d, c = status.cache || {}, m = status.metrics || {};
$("metric-h3").textContent = fmt(m.http3_requests);
$("metric-h3-active").textContent = fmt(m.http3_active_connections || 0);
const cacheHits = c.hits == null ? null : Number(c.hits), cacheMisses = c.misses == null ? null : Number(c.misses);
const cacheEvents = cacheHits !== null && cacheMisses !== null ? cacheHits + cacheMisses : 0;
$("metric-cache-ratio").textContent = cacheEvents > 0 ? `${fmt(cacheHits / cacheEvents * 100, 1)}%` : "-";