Add Linux server monitor dashboard

This commit is contained in:
yhlhoh committed 2026-10-21 12:05:29 +08:00
1 parent 0446648ed1
commit 315cb36a21
19 files changed
+5997 -1

No files matched your search

+286
View File
@@ -0,0 +1,286 @@
"""Deterministic, realistic demo data for UI development and screenshots."""
from __future__ import annotations
import datetime as dt
import math
import random
import time
from typing import Any, Dict, List
from .metrics import build_alerts
class DemoSource:
"""A drop-in metrics source that simulates a busy Linux edge server."""
def __init__(self) -> None:
self.step = 0
self.rng = random.Random(20260609)
self._cores = 16
self._total_mem = 32 * 1024 ** 3
now = dt.datetime.now().astimezone()
offset = now.utcoffset()
self._tz_offset = int(offset.total_seconds()) if offset else 0
self._tz_name = now.tzname() or "LOCAL"
self._boot_base = time.time() - (12 * 86400 + 4 * 3600 + 27 * 60 + 18)
def snapshot(self) -> Dict[str, Any]:
return self.sample()
def sample(self) -> Dict[str, Any]:
self.step += 1
s = self.step
now = time.time()
uptime = 12 * 86400 + 4 * 3600 + 27 * 60 + 18 + s
cpu_base = 36 + 15 * math.sin(s / 15.0) + 5 * math.sin(s / 3.7) + self.rng.uniform(-2.2, 2.2)
cpu_base = max(8.0, min(88.0, cpu_base))
per_core = []
for index in range(self._cores):
value = cpu_base + 13 * math.sin(s / (7.0 + index * 0.6) + index * 0.9) + self.rng.uniform(-4, 4)
per_core.append(round(max(1.0, min(99.0, value)), 1))
cpu_percent = round(sum(per_core) / len(per_core), 1)
mem_percent = 61.5 + 4.5 * math.sin(s / 37.0) + 1.2 * math.sin(s / 9.0)
mem_percent = max(30.0, min(92.0, mem_percent))
total_mem = self._total_mem
used_mem = int(total_mem * mem_percent / 100.0)
available = total_mem - used_mem
free = int(available * 0.32)
buffers = int(total_mem * 0.018)
cached = int(total_mem * 0.235 + 1.5 * 1024 ** 3 * math.sin(s / 25.0))
apps = max(0, total_mem - free - buffers - cached)
swap_total = 8 * 1024 ** 3
swap_used = int(swap_total * (0.045 + 0.012 * math.sin(s / 19.0)))
swap_percent = round(swap_used / swap_total * 100, 1)
load1 = max(0.15, self._cores * cpu_percent / 100.0 * 0.92 + 0.25)
load5 = load1 * 0.94 + 0.08
load15 = load1 * 0.87 + 0.14
total_root = 512 * 1024 ** 3
total_data = 4 * 1024 ** 4
total_var = 128 * 1024 ** 3
total_boot = 1024 ** 3
disks = [
self._disk("/dev/nvme0n1p2", "/", "ext4", total_root, 46.4 + 0.3 * math.sin(s / 40)),
self._disk("/dev/nvme1n1", "/data", "xfs", total_data, 91.2 + 0.08 * math.sin(s / 55)),
self._disk("/dev/nvme0n1p3", "/var", "ext4", total_var, 67.8 + 0.4 * math.sin(s / 30)),
self._disk("/dev/nvme0n1p1", "/boot", "ext4", total_boot, 23.6),
]
read_mbps = 17.4 + 7.5 * math.sin(s / 6.0) + self.rng.uniform(-2, 2)
write_mbps = 6.1 + 3.2 * math.cos(s / 8.0) + self.rng.uniform(-1, 1)
read2 = 2.1 + 1.7 * math.sin(s / 5.0 + 1.4)
write2 = 1.2 + 0.9 * math.cos(s / 7.0)
disk_devices = [
{
"device": "nvme0n1",
"read_bps": int(read_mbps * 1024 ** 2),
"write_bps": int(write_mbps * 1024 ** 2),
"read_iops": round(780 + 240 * math.sin(s / 5), 1),
"write_iops": round(310 + 130 * math.cos(s / 6), 1),
"util_percent": round(min(99.0, 31 + 18 * math.sin(s / 9)), 1),
"read_await_ms": 0.31,
"write_await_ms": 0.44,
},
{
"device": "nvme1n1",
"read_bps": int(max(0, read2) * 1024 ** 2),
"write_bps": int(max(0, write2) * 1024 ** 2),
"read_iops": round(112 + 44 * math.sin(s / 4), 1),
"write_iops": round(86 + 25 * math.cos(s / 5), 1),
"util_percent": round(min(99.0, 12 + 8 * math.sin(s / 7 + 2)), 1),
"read_await_ms": 0.18,
"write_await_ms": 0.22,
},
]
rx_mbps = 12.6 + 5.2 * math.sin(s / 11.0) + 1.5 * math.sin(s / 2.9) + self.rng.uniform(-0.5, 0.5)
tx_mbps = 3.4 + 1.8 * math.cos(s / 9.0) + self.rng.uniform(-0.25, 0.25)
rx2_mbps = 1.35 + 0.55 * math.sin(s / 13.0 + 1.1)
tx2_mbps = 0.42 + 0.2 * math.cos(s / 10.0)
rx_bps = int(max(0, rx_mbps) * 1024 ** 2)
tx_bps = int(max(0, tx_mbps) * 1024 ** 2)
interfaces = [
self._iface("ens18", "10.20.4.17", rx_bps, tx_bps, 10_000, primary=True),
self._iface("ens19", "172.18.4.21", int(max(0, rx2_mbps) * 1024 ** 2), int(max(0, tx2_mbps) * 1024 ** 2), 1000),
self._iface("wg0", "10.88.0.2", int(0.82 * 1024 ** 2), int(0.31 * 1024 ** 2), None, virtual=True),
]
processes = self._processes(total_mem)
temp = round(53.2 + 2.6 * math.sin(s / 17.0), 1)
freq = int(3798 + 120 * math.sin(s / 5.0))
alerts = build_alerts(
cpu_percent=cpu_percent,
memory_percent=mem_percent,
swap_percent=swap_percent,
load1=load1,
cores=self._cores,
disks=disks,
temp_c=temp,
)
return {
"ts": now,
"version": "1.0.0",
"host": {
"hostname": "orion-edge-07",
"os": "Debian GNU/Linux 12 (bookworm)",
"kernel": "6.1.0-28-amd64",
"arch": "x86_64",
"cpu_model": "AMD Ryzen 7 5800X 8-Core Processor",
"cores": self._cores,
"physical_cores": 8,
"primary_ip": "10.20.4.17",
"ips": ["10.20.4.17", "10.88.0.2", "172.18.4.21"],
"boot_epoch": now - uptime,
"uptime_seconds": uptime,
"tz_offset": self._tz_offset,
"tz_name": self._tz_name,
"process_count": 214,
"thread_count": 438,
"version": "1.0.0",
"demo": True,
},
"cpu": {
"percent": cpu_percent,
"per_core": per_core,
"breakdown": {
"user": round(cpu_percent * 0.61, 1),
"nice": 0.3,
"system": round(cpu_percent * 0.27, 1),
"iowait": round(cpu_percent * 0.07, 1),
"irq": round(cpu_percent * 0.02, 1),
"softirq": round(cpu_percent * 0.02, 1),
"steal": 0.1,
},
"freq_mhz": freq,
"temp_c": temp,
"temp_label": "x86_pkg_temp",
"model": "AMD Ryzen 7 5800X 8-Core Processor",
"cores": self._cores,
"physical_cores": 8,
},
"memory": {
"total": total_mem,
"used": used_mem,
"free": free,
"available": available,
"buffers": buffers,
"cached": cached,
"apps": apps,
"percent": round(mem_percent, 1),
"composition": {
"apps": apps,
"cache": cached,
"buffers": buffers,
"free": free,
},
"swap_total": swap_total,
"swap_used": swap_used,
"swap_free": swap_total - swap_used,
"swap_percent": swap_percent,
"dirty": 48 * 1024 ** 2,
"writeback": 0,
},
"load": {
"load1": round(load1, 2),
"load5": round(load5, 2),
"load15": round(load15, 2),
"running": 3,
"threads": 438,
"percent": round(load1 / self._cores * 100, 1),
},
"disks": disks,
"disk_io": {
"devices": disk_devices,
"read_bps": sum(d["read_bps"] for d in disk_devices),
"write_bps": sum(d["write_bps"] for d in disk_devices),
},
"network": {
"interfaces": interfaces,
"interface_count": 3,
"total_rx_bps": rx_bps + int(max(0, rx2_mbps) * 1024 ** 2),
"total_tx_bps": tx_bps + int(max(0, tx2_mbps) * 1024 ** 2),
"primary_iface": "ens18",
"primary_ip": "10.20.4.17",
"all_ips": ["10.20.4.17", "10.88.0.2", "172.18.4.21"],
"errors": 0,
"drops": 0,
},
"processes": processes,
"alerts": alerts,
}
def _disk(self, device: str, mount: str, fstype: str, total: int, percent: float) -> Dict[str, Any]:
used = int(total * percent / 100)
free = total - used
return {
"device": device,
"mount": mount,
"fstype": fstype,
"total": total,
"used": used,
"free": free,
"percent": round(percent, 1),
"readonly": False,
"inodes_total": 100_000_000,
"inodes_free": 80_000_000,
}
def _iface(
self,
name: str,
ip: str,
rx_bps: int,
tx_bps: int,
speed: int | None,
primary: bool = False,
virtual: bool = False,
) -> Dict[str, Any]:
return {
"name": name,
"ip": ip,
"virtual": virtual,
"primary": primary,
"rx_bps": rx_bps,
"tx_bps": tx_bps,
"rx_total": 18_400_000_000_000 + rx_bps * 37,
"tx_total": 4_700_000_000_000 + tx_bps * 29,
"errors": 0,
"drops": 0,
"speed_mbps": speed,
"link": True,
}
def _processes(self, total_mem: int) -> List[Dict[str, Any]]:
rows = [
("node", 2203, 18.4, 3.1, "node /opt/edge-api/dist/server.js --cluster 4"),
("java", 4080, 14.1, 12.6, "java -Xms4g -Xmx6g -jar /opt/events/event-worker.jar"),
("postgres", 1442, 12.8, 8.4, "postgres: checkpointer"),
("python3", 3120, 7.6, 1.5, "python3 /opt/telemetry/collector.py --workers 8"),
("nginx", 2101, 4.2, 0.8, "nginx: worker process"),
("dockerd", 910, 2.1, 1.2, "/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock"),
("systemd-journald", 512, 1.8, 0.3, "/lib/systemd/systemd-journald"),
("redis-server", 1750, 1.2, 0.7, "redis-server 0.0.0.0:6379"),
("containerd", 1002, 0.8, 0.4, "/usr/bin/containerd"),
("kworker/3:2", 88, 0.4, 0.0, "[kworker/3:2-events]"),
("rsyslogd", 702, 0.2, 0.1, "/usr/sbin/rsyslogd -n -iNONE"),
("sshd", 2402, 0.1, 0.1, "sshd: /usr/sbin/sshd -D [listener]"),
]
out = []
for name, pid, cpu, mem, cmd in rows:
rss = int(total_mem * mem / 100)
out.append({
"pid": pid,
"name": name,
"cmd": cmd,
"cpu_percent": cpu,
"mem_percent": mem,
"rss_bytes": rss,
"threads": 1 if name.startswith("kworker") else 24,
})
return out