153 lines
4.3 KiB
JavaScript
153 lines
4.3 KiB
JavaScript
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,
|
|
} |