import Chart from "https://cdn.jsdelivr.net/npm/chart.js@4.2.1/auto/+esm" function qpush(arr, val, len) { arr.push(val) if (arr.length > len) { arr.shift() } } class Stat { constructor() { this.Stat = {} this.LastStat = {} } async update() { let resp = await fetch("proc/stat") let stext = await resp.text() let lines = stext.split("\n") this.Date = new Date(resp.headers.get("Date")) this.LastStat = this.Stat this.Stat = {} for (let line of lines) { let parts = line.split(/\s+/) let key = parts.shift() let vals = parts.map(Number) this.Stat[key] = vals } } cpu(n="") { let key = `cpu${n}` let vals = this.Stat[key] let prev = this.LastStat[key] if (!vals || !prev) { return {} } let total = vals.reduce((a,b)=>a+b) - prev.reduce((a,b)=>a+b) return { user: (vals[0] - prev[0]) / total, nice: (vals[1] - prev[1]) / total, sys: (vals[2] - prev[2]) / total, idle: (vals[3] - prev[3]) / total, wait: (vals[4] - prev[4]) / total, irq: (vals[5] - prev[5]) / total, softirq: (vals[6] - prev[6]) / total, steal: (vals[7] - prev[7]) / total, guest: (vals[8] - prev[8]) / total, guestNice: (vals[9] - prev[9]) / total, } } } class AreaChart { constructor(element, stat, width=60) { this.stat = stat this.width = width this.canvas = element.appendChild(document.createElement("canvas")) this.data ={ labels: [], datasets: [] } this.datasets = {} for (let label of ["user", "nice", "sys", "idle", "wait"]) { let d = [] this.data.datasets.push({ label: label, data: d, }) this.datasets[label] = d } this.chart = new Chart( this.canvas, { type: "line", data: this.data, options: { responsive: true, pointStyle: false, scales: { x: { title: { display: false }, ticks: { display: false }, grid: { display: false }, }, y: { stacked: true, ticks: { display: false }, } } } } ) } async update() { let cpu = this.stat.cpu() qpush(this.data.labels, this.stat.Date, this.width) qpush(this.datasets.user, cpu.user, this.width) qpush(this.datasets.nice, cpu.nice, this.width) qpush(this.datasets.sys, cpu.sys, this.width) qpush(this.datasets.idle, cpu.idle, this.width) qpush(this.datasets.wait, cpu.wait, this.width) this.chart.update() } } class PieChart { constructor(element, stat) { this.stat = stat this.canvas = element.appendChild(document.createElement("canvas")) this.data ={ labels: ["user", "nice", "sys", "idle", "wait"], datasets: [] } this.chart = new Chart( this.canvas, { type: "pie", data: this.data, options: { animation: false, borderWidth: 0, backgroundColor: [ "blue", "red", "orange", "rgba(255, 255, 0, 0.2)", "cyan", ], plugins: { legend: { display: false }, }, }, } ) } async update() { let cpu = this.stat.cpu() this.data.datasets = [{ label: "Current", data: [cpu.user, cpu.nice, cpu.sys, cpu.idle, cpu.wait], }] this.chart.update() } } export { Stat, AreaChart, PieChart, }