v0.24.8
This commit is contained in:
1 parent
579d9c806b
commit
1297ea2920
34 files changed
+320
-96
No files matched your search
+30
-4
@@ -506,7 +506,7 @@ $("reload-certificates").addEventListener("click", async () => {
|
||||
$("reset-certificate").addEventListener("click", () => $("certificate-form").reset());
|
||||
|
||||
// Dashboard metrics are actual server samples. Null means unavailable, not zero.
|
||||
let systemSamples = [], connectionOpenSamples = [], connectionExchangeSamples = [], cacheMemorySamples = [], cacheHitSamples = [], cacheMissSamples = [], cacheBypassSamples = [], lastCacheCounters = null,
|
||||
let systemSamples = [], connectionOpenSamples = [], connectionExchangeSamples = [], cacheMemorySamples = [], cacheTransientSamples = [], cacheFillSamples = [], cacheColdQueueSamples = [], cacheColdIoSamples = [], cacheColdStorageSamples = [], cacheHitSamples = [], cacheMissSamples = [], cacheBypassSamples = [], lastCacheCounters = null,
|
||||
processCpuSamples = [], processRssSamples = [], networkRxSamples = [], networkTxSamples = [], responseLatencySamples = [], networkInterfaceSamples = new Map(), settingsDirty = new Set();
|
||||
const hiddenNetworkInterfaces = (() => {
|
||||
try {
|
||||
@@ -545,6 +545,12 @@ function knownPair(left, right, format, zeroRight = null) {
|
||||
const rightText = right === 0 && zeroRight ? zeroRight : format(right);
|
||||
return `${format(left)} / ${rightText}`;
|
||||
}
|
||||
function occupancyText(used, limit) {
|
||||
if (used == null) return "-";
|
||||
const usedNumber = Number(used), limitNumber = Number(limit);
|
||||
if (!Number.isFinite(limitNumber) || limitNumber <= 0) return fmtBytes(usedNumber);
|
||||
return `${fmtBytes(usedNumber)} / ${fmtBytes(limitNumber)} · ${fmt(usedNumber / limitNumber * 100, 1)}%`;
|
||||
}
|
||||
function sparklinePoints(values, width = 300, height = 60, padding = 5, peakOverride = null) {
|
||||
const peak = Math.max(1, peakOverride ?? Math.max(0, ...values));
|
||||
return values.map((value, index) => `${index * width / Math.max(1, values.length - 1)},${height - padding - Math.max(0, value) / peak * (height - padding * 2)}`).join(" ");
|
||||
@@ -642,6 +648,12 @@ function renderDiagnostics(status, appendSample = true) {
|
||||
$("cache-evictions").textContent = `${fmt(c.evictions)} / ${fmt(c.expired)}`;
|
||||
if (appendSample) {
|
||||
if (c.resident_bytes != null) { cacheMemorySamples.push(Number(c.resident_bytes)); cacheMemorySamples = cacheMemorySamples.slice(-60); }
|
||||
if (c.transient_bytes != null) { cacheTransientSamples.push(Number(c.transient_bytes)); cacheTransientSamples = cacheTransientSamples.slice(-60); }
|
||||
if (c.fill_bytes_active != null) { cacheFillSamples.push(Number(c.fill_bytes_active)); cacheFillSamples = cacheFillSamples.slice(-60); }
|
||||
if (c.cold_queue_bytes != null) { cacheColdQueueSamples.push(Number(c.cold_queue_bytes)); cacheColdQueueSamples = cacheColdQueueSamples.slice(-60); }
|
||||
const coldIoBytes = (Number(c.cold_write_bytes_active) || 0) + (Number(c.cold_read_bytes_active) || 0);
|
||||
if (c.cold_write_bytes_active != null || c.cold_read_bytes_active != null) { cacheColdIoSamples.push(coldIoBytes); cacheColdIoSamples = cacheColdIoSamples.slice(-60); }
|
||||
if (c.cold_bytes != null) { cacheColdStorageSamples.push(Number(c.cold_bytes)); cacheColdStorageSamples = cacheColdStorageSamples.slice(-60); }
|
||||
const currentCounters = [c.hits, c.misses, c.bypasses].map(Number);
|
||||
if (currentCounters.every(Number.isFinite)) {
|
||||
const delta = lastCacheCounters ? currentCounters.map((value, index) => value >= lastCacheCounters[index] ? value - lastCacheCounters[index] : 0) : [0, 0, 0];
|
||||
@@ -658,8 +670,22 @@ function renderDiagnostics(status, appendSample = true) {
|
||||
$("cache-bypass-sparkline").setAttribute("points", sparklinePoints(cacheBypassSamples, 300, 60, 5, cacheOutcomePeak));
|
||||
const latestCacheDelta = [cacheHitSamples.at(-1), cacheMissSamples.at(-1), cacheBypassSamples.at(-1)];
|
||||
$("cache-outcome-chart-value").textContent = latestCacheDelta.every(value => value != null) ? latestCacheDelta.map(value => fmt(value)).join(" / ") : "-";
|
||||
$("cache-memory-sparkline").setAttribute("points", sparklinePoints(cacheMemorySamples));
|
||||
$("cache-chart-value").textContent = fmtBytes(c.resident_bytes);
|
||||
const hotLimit = Number(c.hot_limit_bytes), hotPeak = Number.isFinite(hotLimit) && hotLimit > 0 ? Math.max(hotLimit, ...cacheMemorySamples) : null;
|
||||
$("cache-memory-sparkline").setAttribute("points", sparklinePoints(cacheMemorySamples, 300, 60, 5, hotPeak));
|
||||
$("cache-chart-value").textContent = occupancyText(c.resident_bytes, c.hot_limit_bytes);
|
||||
const transientLimit = Number(c.transient_limit_bytes);
|
||||
const transientPeak = Number.isFinite(transientLimit) && transientLimit > 0
|
||||
? Math.max(transientLimit, ...cacheTransientSamples, ...cacheFillSamples, ...cacheColdQueueSamples, ...cacheColdIoSamples)
|
||||
: Math.max(1, ...cacheTransientSamples, ...cacheFillSamples, ...cacheColdQueueSamples, ...cacheColdIoSamples);
|
||||
$("cache-transient-sparkline").setAttribute("points", sparklinePoints(cacheTransientSamples, 300, 60, 5, transientPeak));
|
||||
$("cache-fill-sparkline").setAttribute("points", sparklinePoints(cacheFillSamples, 300, 60, 5, transientPeak));
|
||||
$("cache-queue-sparkline").setAttribute("points", sparklinePoints(cacheColdQueueSamples, 300, 60, 5, transientPeak));
|
||||
$("cache-io-sparkline").setAttribute("points", sparklinePoints(cacheColdIoSamples, 300, 60, 5, transientPeak));
|
||||
$("cache-transient-chart-value").textContent = occupancyText(c.transient_bytes, c.transient_limit_bytes);
|
||||
const coldEnabled = envelope?.config.cache?.cold_enabled === true;
|
||||
const coldLimit = Number(c.cold_limit_bytes), coldPeak = Number.isFinite(coldLimit) && coldLimit > 0 ? Math.max(coldLimit, ...cacheColdStorageSamples) : null;
|
||||
$("cache-cold-sparkline").setAttribute("points", sparklinePoints(cacheColdStorageSamples, 300, 60, 5, coldPeak));
|
||||
$("cache-cold-chart-value").textContent = coldEnabled ? occupancyText(c.cold_bytes, c.cold_limit_bytes) : t("notEnabled");
|
||||
setOptionalMetric("process-platform", !!d.platform && d.platform !== "Unsupported", d.platform || "");
|
||||
setOptionalMetric("process-cpu", d.process_cpu_percent != null, `${fmt(d.process_cpu_percent, 1)}%`);
|
||||
const fds = knownPair(d.open_fds, d.max_fds, value => fmt(value), t("unlimited"));
|
||||
@@ -752,7 +778,7 @@ function renderSettings() {
|
||||
if (!settingsDirty.has("response-form")) {
|
||||
const server = config.server_header || {}, compression = config.compression || {}, diagnostics = config.diagnostic_headers || {};
|
||||
$("expose-request-id").checked = !!diagnostics.request_id;
|
||||
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.24.7";
|
||||
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.24.8";
|
||||
for (const name of ["gzip", "br", "zstd", "deflate"]) $(`compress-${name}`).checked = !!compression[name];
|
||||
$("compress-min").value = compression.min_bytes ?? 1024; syncServerMode();
|
||||
}
|
||||
|
||||
+48
-10
@@ -294,12 +294,43 @@
|
||||
class="cache-bypass-key">BYPASS</span></div>
|
||||
</div>
|
||||
<div class="mini-live-chart">
|
||||
<div class="mini-live-chart-head"><span data-i18n="cacheResidentHistory">Resident
|
||||
RAM history</span><b id="cache-chart-value">-</b></div>
|
||||
<svg aria-label="RAM cache resident bytes history"
|
||||
data-i18n-aria="cacheResidentHistory" role="img" viewbox="0 0 300 60">
|
||||
<div class="mini-live-chart-head"><span data-i18n="cacheHotMemoryHistory">HOT RAM
|
||||
usage / limit</span><b id="cache-chart-value">-</b></div>
|
||||
<svg aria-label="HOT cache RAM usage history"
|
||||
data-i18n-aria="cacheHotMemoryHistory" role="img" viewbox="0 0 300 60">
|
||||
<path class="chart-grid" d="M0 15H300 M0 30H300 M0 45H300"></path>
|
||||
<polyline class="diagnostic-line" id="cache-memory-sparkline"
|
||||
<polyline class="diagnostic-line cache-hot-line" id="cache-memory-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="mini-live-chart">
|
||||
<div class="mini-live-chart-head"><span data-i18n="cacheTransientMemoryHistory">Transient
|
||||
RAM usage / limit</span><b id="cache-transient-chart-value">-</b></div>
|
||||
<svg aria-label="Transient cache RAM usage history"
|
||||
data-i18n-aria="cacheTransientMemoryHistory" role="img" viewbox="0 0 300 60">
|
||||
<path class="chart-grid" d="M0 15H300 M0 30H300 M0 45H300"></path>
|
||||
<polyline class="diagnostic-line cache-transient-total-line" id="cache-transient-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
<polyline class="diagnostic-line cache-fill-line" id="cache-fill-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
<polyline class="diagnostic-line cache-queue-line" id="cache-queue-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
<polyline class="diagnostic-line cache-io-line" id="cache-io-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
</svg>
|
||||
<div class="mini-chart-legend" aria-hidden="true"><span
|
||||
class="cache-transient-total-key" data-i18n="cacheTransientShort">TOTAL</span><span
|
||||
class="cache-fill-key" data-i18n="cacheFillShort">fill</span><span
|
||||
class="cache-queue-key" data-i18n="cacheQueueShort">cold queue</span><span
|
||||
class="cache-io-key" data-i18n="cacheIoShort">cold I/O</span></div>
|
||||
</div>
|
||||
<div class="mini-live-chart">
|
||||
<div class="mini-live-chart-head"><span data-i18n="cacheColdStorageHistory">COLD storage
|
||||
usage / limit</span><b id="cache-cold-chart-value">-</b></div>
|
||||
<svg aria-label="COLD storage usage history"
|
||||
data-i18n-aria="cacheColdStorageHistory" role="img" viewbox="0 0 300 60">
|
||||
<path class="chart-grid" d="M0 15H300 M0 30H300 M0 45H300"></path>
|
||||
<polyline class="diagnostic-line cache-cold-line" id="cache-cold-sparkline"
|
||||
points="0,55 300,55"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
@@ -307,8 +338,16 @@
|
||||
</article>
|
||||
<article class="card">
|
||||
<div class="mini-heading">
|
||||
<h3 data-i18n="processDiagnostics">Process</h3><span class="meta"
|
||||
id="system-sample-age">-</span>
|
||||
<h3 data-i18n="processDiagnostics">Process</h3>
|
||||
<div class="mini-heading-actions">
|
||||
<details class="metric-info">
|
||||
<summary data-i18n-aria="memoryAccountingInfo" aria-label="Memory accounting information">i</summary>
|
||||
<div class="metric-info-popover">
|
||||
<p class="fine" data-i18n="memoryAccountingHint">RSS is the real process footprint. HOT/transient cache values are RustProxy-accounted allocations; transform memory is a conservative active reservation. Non-cache RSS is RSS minus accounted cache and includes transforms, connections, TLS, logging, Tokio/runtime state, allocator overhead and other buffers, so these rows are not all additive.</p>
|
||||
</div>
|
||||
</details>
|
||||
<span class="meta" id="system-sample-age">-</span>
|
||||
</div>
|
||||
</div>
|
||||
<dl class="mini-metrics">
|
||||
<div>
|
||||
@@ -380,7 +419,6 @@
|
||||
<dd id="cgroup-memory">-</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p class="fine" data-i18n="memoryAccountingHint">RSS is the real process footprint. HOT/transient cache values are RustProxy-accounted allocations; transform memory is a conservative active reservation. Non-cache RSS is RSS minus accounted cache and includes transforms, connections, TLS, logging, Tokio/runtime state, allocator overhead and other buffers, so these rows are not all additive.</p>
|
||||
<div class="mini-live-chart-stack">
|
||||
<div class="mini-live-chart">
|
||||
<div class="mini-live-chart-head"><span data-i18n="processCpuHistory">Process CPU
|
||||
@@ -1353,7 +1391,7 @@
|
||||
<option data-i18n="serverCustom" value="custom">Replace / add custom value</option>
|
||||
</select>
|
||||
<label data-i18n="serverValue" for="server-value">Custom Server value</label><input
|
||||
id="server-value" maxlength="256" placeholder="RustProxy/v0.24.7"
|
||||
id="server-value" maxlength="256" placeholder="RustProxy/v0.24.8"
|
||||
spellcheck="false" />
|
||||
<h3 class="subheading" data-i18n="diagnosticHeaders">Diagnostic headers</h3>
|
||||
<div class="switch-grid">
|
||||
@@ -2060,7 +2098,7 @@
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="page-footer"><span>RustProxy <b>0.24.7</b></span><span id="footer-status">API - /
|
||||
<footer class="page-footer"><span>RustProxy <b>0.24.8</b></span><span id="footer-status">API - /
|
||||
dropped: 0</span></footer>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
+92
-1
@@ -7351,4 +7351,95 @@ body[data-density="compact"] .page-footer {
|
||||
#cache-memory-warning {
|
||||
color: var(--notice-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
/* 0.24.8 cache occupancy charts and compact memory-accounting help */
|
||||
.mini-heading-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 7px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.metric-info {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.metric-info>summary {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 50%;
|
||||
color: var(--muted);
|
||||
background: var(--panel2);
|
||||
font: 700 10px var(--mono);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.metric-info>summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.metric-info>summary:hover,
|
||||
.metric-info>summary:focus-visible,
|
||||
.metric-info[open]>summary {
|
||||
color: var(--text);
|
||||
border-color: var(--border-hover);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.metric-info-popover {
|
||||
position: absolute;
|
||||
z-index: 40;
|
||||
top: calc(100% + 7px);
|
||||
right: 0;
|
||||
width: min(360px, calc(100vw - 44px));
|
||||
padding: 10px 11px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
background: var(--panel2);
|
||||
box-shadow: 0 12px 30px var(--shadow-mid);
|
||||
}
|
||||
|
||||
.metric-info-popover .fine {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.cache-hot-line,
|
||||
.cache-transient-total-line {
|
||||
stroke: var(--accent);
|
||||
}
|
||||
|
||||
.cache-fill-line {
|
||||
stroke: var(--green);
|
||||
}
|
||||
|
||||
.cache-queue-line,
|
||||
.cache-cold-line {
|
||||
stroke: var(--blue);
|
||||
}
|
||||
|
||||
.cache-io-line {
|
||||
stroke: var(--transform-chart);
|
||||
}
|
||||
|
||||
.cache-transient-total-key {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.cache-fill-key {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.cache-queue-key {
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
.cache-io-key {
|
||||
color: var(--transform-chart);
|
||||
}
|
||||
@@ -600,7 +600,7 @@
|
||||
authMode.addEventListener("change", syncAuth); syncAuth();
|
||||
g = group("vhResponsePolicy"); const server = value.server_header, diagnostics = value.diagnostic_headers;
|
||||
const serverMode = field(g, "server-mode", "serverHeader", server?.mode || "inherit", "select", { values: [["inherit", "vhInherit"], ["preserve", "serverPreserve"], ["hide", "serverHide"], ["custom", "serverCustom"]] });
|
||||
const serverValue = field(g, "server-value", "serverValue", server?.value || "RustProxy/v0.24.7", "text", { maxLength: 256 });
|
||||
const serverValue = field(g, "server-value", "serverValue", server?.value || "RustProxy/v0.24.8", "text", { maxLength: 256 });
|
||||
const syncServer = () => { serverValue.disabled = serverMode.value !== "custom"; serverValue.required = !serverValue.disabled; }; serverMode.addEventListener("change", syncServer); syncServer();
|
||||
const inheritDiagnostics = field(g, "diag-inherit", "diagInherit", !diagnostics, "checkbox"), diagInputs = [];
|
||||
for (const [name, key] of [["request_id", "diagRequestId"]]) diagInputs.push(field(g, `diag-${name}`, key, diagnostics?.[name] ?? envelope?.config.diagnostic_headers?.[name], "checkbox"));
|
||||
|
||||
Reference in new issue
Block a user