164 lines
5.1 KiB
JavaScript
164 lines
5.1 KiB
JavaScript
function fmt(units, overflow, multiplier = 1) {
|
|
return function(val) {
|
|
let max = 1;
|
|
for(let i = 0; i < units.length; i++) {
|
|
let next = max * units[i][1];
|
|
if(val < next) {
|
|
const number = Math.floor((val) / max);
|
|
const unit = units[i][0];
|
|
return number + " " + (number === 1 ? unit.slice(0, -1) : unit);
|
|
}
|
|
max = next;
|
|
}
|
|
return overflow;
|
|
}
|
|
}
|
|
|
|
const fmtSize = fmt([["B", 1024], ["KiB", 1024], ["MiB", 1024], ["GiB", 1024], ["TiB", 1024], ["PiB", 1024], ["ZiB", 1024], ["YiB", 1024]], "quite a lot", 1);
|
|
const fmtTime = fmt([["seconds", 60], ["minutes", 60], ["hours", 24], ["days", 60], ["weeks", 7], ["months", 4]], "an eternity");
|
|
|
|
function createGraph(color, max) {
|
|
const canvas = document.createElement("canvas");
|
|
const ctx = canvas.getContext("2d");
|
|
const ogWidth = canvas.clientWidth;
|
|
const ogHeight = canvas.clientHeight;
|
|
const points = [];
|
|
|
|
function update(val) {
|
|
points.unshift(val);
|
|
if(points.length > 100) points.pop();
|
|
|
|
canvas.width = canvas.clientWidth;
|
|
canvas.height = canvas.clientHeight;
|
|
ctx.width = canvas.clientWidth;
|
|
ctx.height = canvas.clientHeight;
|
|
|
|
ctx.strokeStyle = color;
|
|
ctx.fillStyle = color + "66";
|
|
ctx.lineWidth = 3;
|
|
|
|
ctx.clearRect(0, 0, 4000, 4000);
|
|
const firsth = canvas.clientHeight - (points[0] / max) * canvas.clientHeight;
|
|
ctx.moveTo(canvas.clientWidth, firsth);
|
|
for(let i = 1; i < points.length; i++) {
|
|
ctx.lineTo(canvas.clientWidth - i * 10, canvas.clientHeight - (points[i] / max) * canvas.clientHeight);
|
|
}
|
|
|
|
ctx.stroke();
|
|
ctx.lineTo(canvas.clientWidth - points.length * 10 + 10, canvas.clientHeight);
|
|
ctx.lineTo(canvas.clientWidth, canvas.clientHeight);
|
|
ctx.fill();
|
|
}
|
|
|
|
return { canvas, update };
|
|
}
|
|
|
|
function createMeter(name, color, max, fmt) {
|
|
const wrapper = document.createElement("div");
|
|
const side = document.createElement("div");
|
|
const title = document.createElement("div");
|
|
const display = document.createElement("div");
|
|
const subtitle = document.createElement("div");
|
|
const graph = createGraph(color, max || 100);
|
|
|
|
wrapper.style.color = color;
|
|
wrapper.classList.add("block");
|
|
subtitle.style.fontSize = "0.5em";
|
|
subtitle.innerText = max !== 0 ? "of " + fmt(max || 100) : "";
|
|
title.style.fontSize = "0.5em";
|
|
title.innerText = name;
|
|
|
|
side.append(title);
|
|
side.append(display);
|
|
side.append(subtitle);
|
|
wrapper.append(graph.canvas);
|
|
wrapper.append(side);
|
|
|
|
function update(val) {
|
|
graph.update(val);
|
|
display.innerText = fmt ? fmt(val) : Math.floor((val / (max || 100)) * 1e4) / 1e2 + "%";
|
|
}
|
|
|
|
return { element: wrapper, update }
|
|
}
|
|
|
|
function main() {
|
|
let ws = null;
|
|
let netintotal = 0;
|
|
let netouttotal = 0;
|
|
let refresh = () => {};
|
|
const stats = {};
|
|
|
|
function init() {
|
|
// document.querySelector("main").innerHTML = '<p>The server<span id="server"></span> has been <span id="online">online</span> for <span id="time">a while</span>.</p><p>It\'s sending <span id="netout">stuff</span> and recieving <span id="netin">more stuff</span>, for a total of <span id="netouttotal">???</span> out and <span id="netintotal">???</span> in.</p>';
|
|
document.querySelector("main").innerHTML = '<p>The server<span id="server"></span> has been <span id="online">online</span> for <span id="time">a while</span>.</p>';
|
|
|
|
const memory = createMeter("used memory", "#41ead4", stats.memtotal, fmtSize);
|
|
const cpu = createMeter("avg. cpu usage", "#8963ba", 0);
|
|
const disk = createMeter("disk usage", "#f06449", stats.disktotal, fmtSize);
|
|
document.body.append(memory.element);
|
|
document.body.append(cpu.element);
|
|
document.body.append(disk.element);
|
|
|
|
function update() {
|
|
memory.update(stats.memused);
|
|
cpu.update(stats.cpuusage);
|
|
disk.update(stats.diskused);
|
|
|
|
netintotal += stats.netin;
|
|
netouttotal += stats.netout;
|
|
|
|
document.getElementById("time").innerText = fmtTime(stats.uptime);
|
|
document.getElementById("server").innerText = ` (${stats.hostname})`;
|
|
// document.getElementById("netin").innerText = fmtSize(stats.netin);
|
|
// document.getElementById("netout").innerText = fmtSize(stats.netout);
|
|
document.getElementById("netintotal").innerText = fmtSize(netintotal);
|
|
document.getElementById("netouttotal").innerText = fmtSize(netouttotal);
|
|
}
|
|
|
|
setInterval(update, 1000);
|
|
refresh = update;
|
|
update();
|
|
}
|
|
|
|
function reconnect() {
|
|
document.getElementById("online").innerText = "offline";
|
|
stats.uptime = 0;
|
|
stats.netin = 0;
|
|
stats.netout = 0;
|
|
const wait = setInterval(() => stats.uptime += 1, 1000);
|
|
|
|
function retry() {
|
|
ws = new WebSocket(`wss://${location.host}/stats/live`);
|
|
ws.onmessage = (msg) => Object.assign(stats, JSON.parse(msg.data));
|
|
ws.onclose = retry;
|
|
ws.onopen = () => {
|
|
ws.send("sync");
|
|
document.getElementById("online").innerText = "online";
|
|
clearInterval(wait);
|
|
refresh();
|
|
};
|
|
}
|
|
|
|
retry();
|
|
}
|
|
|
|
function connect() {
|
|
ws = new WebSocket(`wss://${location.host}/stats/live`);
|
|
ws.onmessage = (msg) => Object.assign(stats, JSON.parse(msg.data));
|
|
ws.onclose = reconnect;
|
|
ws.onopen = () => {
|
|
ws.send("sync");
|
|
const wait = setInterval(() => {
|
|
if(!stats.memtotal) return;
|
|
clearInterval(wait);
|
|
init();
|
|
}, 100);
|
|
};
|
|
}
|
|
|
|
connect();
|
|
}
|
|
|
|
main();
|
|
|