Show which provider's bytes were slow
Added beside the upstream panel and for the same reason: the owner reported anime stuttering and it took an evening of measurement to establish that the television was fine and TorBox's CDN had dipped to 5.5 Mbps. That is a question a dashboard should answer in a glance. Median rather than mean, because one fast session should not hide ten slow ones, and the share of watched time spent waiting alongside it, because that is the number that matches what the viewer actually felt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7a40dd908d
commit
73a86d3e23
2 changed files with 30 additions and 2 deletions
|
|
@ -195,7 +195,8 @@ routerAdd("GET", "/api/status", (e) => {
|
||||||
// Upstream liveness rides along on the same call rather than a
|
// Upstream liveness rides along on the same call rather than a
|
||||||
// second round trip: it is produced by the same service and read
|
// second round trip: it is produced by the same service and read
|
||||||
// by the same screen.
|
// by the same screen.
|
||||||
upstreams: stats.upstreams }
|
upstreams: stats.upstreams,
|
||||||
|
throughput: stats.throughput }
|
||||||
})
|
})
|
||||||
|
|
||||||
return e.json(200, {
|
return e.json(200, {
|
||||||
|
|
|
||||||
|
|
@ -417,6 +417,33 @@ function sinceLabel(unix){
|
||||||
("0" + d.getMinutes()).slice(-2);
|
("0" + d.getMinutes()).slice(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whose bytes were slow. Not a ranking input and deliberately not per file: a
|
||||||
|
// stall is a property of neither the upload nor the hostname, because TorBox
|
||||||
|
// hands out CDN nodes per request. This exists to answer "was it them or us"
|
||||||
|
// for a person looking at a screen, which is the question that took an evening
|
||||||
|
// of measurement the first time it was asked.
|
||||||
|
function panelThroughput(a){
|
||||||
|
var t = a && a.throughput;
|
||||||
|
if (!t || !t.length) return "";
|
||||||
|
var rows = t.map(function(x){
|
||||||
|
// Mbit/s reads the way a person thinks about a connection; kbps does not.
|
||||||
|
var med = (x.medianKbps / 1000).toFixed(1);
|
||||||
|
var worst = x.worstMinKbps === null ? "—" : (x.worstMinKbps / 1000).toFixed(1);
|
||||||
|
// Time spent waiting is the number that matches what the viewer felt.
|
||||||
|
var stall = x.stalledPct === null ? "—" : x.stalledPct + " %";
|
||||||
|
var bad = x.stalledPct !== null && x.stalledPct >= 2;
|
||||||
|
return "<tr><td><b>" + esc(x.provider) + '</b></td><td class="num">' + x.sessions +
|
||||||
|
'</td><td class="num">' + med + '</td><td class="num">' + worst +
|
||||||
|
'</td><td class="num"' + (bad ? ' style="color:var(--warn)"' : "") + ">" + stall +
|
||||||
|
"</td></tr>";
|
||||||
|
}).join("");
|
||||||
|
return '<section class="wide"><h2>Rychlost zdrojů za 24 h</h2><table>' +
|
||||||
|
'<tr><th>poskytovatel</th><th class="num">relací</th><th class="num">medián Mb/s</th>' +
|
||||||
|
'<th class="num">nejhorší propad</th><th class="num">čekání</th></tr>' + rows +
|
||||||
|
'</table><p class="note">Medián, ne průměr: jedna rychlá relace nemá schovat deset pomalých. ' +
|
||||||
|
"Sloupec čekání je podíl sledovaného času stráveného načítáním.</p></section>";
|
||||||
|
}
|
||||||
|
|
||||||
function panelAccounts(a){
|
function panelAccounts(a){
|
||||||
if (!a || a.error) return "";
|
if (!a || a.error) return "";
|
||||||
return '<section><h2>Účty</h2><div class="kv">' +
|
return '<section><h2>Účty</h2><div class="kv">' +
|
||||||
|
|
@ -1191,7 +1218,7 @@ async function load(){
|
||||||
el("main").innerHTML =
|
el("main").innerHTML =
|
||||||
panelServices(d.coolify) + panelReleases(d.releases) +
|
panelServices(d.coolify) + panelReleases(d.releases) +
|
||||||
panelClients(d.clients) + panelApi(d.amberApi) + panelAccounts(d.accounts) +
|
panelClients(d.clients) + panelApi(d.amberApi) + panelAccounts(d.accounts) +
|
||||||
panelUpstreams(d.amberApi) +
|
panelUpstreams(d.amberApi) + panelThroughput(d.amberApi) +
|
||||||
panelErrors(errs);
|
panelErrors(errs);
|
||||||
wire();
|
wire();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue