feat: 横版col-extra — 负载/SWAP/磁盘/温度/流量/进程 6项指标

SystemInfoCollector 新增:
- swap: SWAP用量 (psutil + /proc/meminfo fallback)
- disk: 磁盘用量
- temperature: CPU温度 (psutil + /sys/class/thermal fallback)

Sentinel col-extra 显示:
  负载 | SWAP | 磁盘 | 温度 | 累计流量 | 进程RSS

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
qinglong
2026-06-14 09:19:37 +08:00
parent 800142402a
commit b1b7cd0563
2 changed files with 88 additions and 2 deletions
+69 -1
View File
@@ -64,9 +64,12 @@ class SystemInfoCollector:
},
"cpu": self._get_cpu(),
"memory": self._get_memory(),
"swap": self._get_swap(),
"disk": self._get_disk(),
"process": self._get_process(),
"network": self._get_network(),
"net_speed": self._get_network_speed()
"net_speed": self._get_network_speed(),
"temperature": self._get_temperature(),
}
def _get_cpu(self) -> Dict[str, Any]:
@@ -107,6 +110,71 @@ class SystemInfoCollector:
logger.warning(f"Memory info failed: {e}")
return {"total_gb": 0, "used_gb": 0, "percent": 0}
def _get_swap(self) -> Dict[str, Any]:
if self.psutil:
try:
s = self.psutil.swap_memory()
return {"total_gb": round(s.total / 1073741824, 1),
"used_gb": round(s.used / 1073741824, 1),
"percent": s.percent}
except Exception:
pass
try:
with open('/proc/meminfo') as f:
mem = {}
for line in f:
parts = line.split()
if len(parts) >= 2:
mem[parts[0].rstrip(':')] = int(parts[1]) * 1024
t = mem.get('SwapTotal', 0)
f_swap = mem.get('SwapFree', mem.get('SwapCached', 0))
if t > 0:
used = t - f_swap
return {"total_gb": round(t / 1073741824, 1),
"used_gb": round(used / 1073741824, 1),
"percent": round((used / t) * 100, 1)}
except Exception:
pass
return {"total_gb": 0, "used_gb": 0, "percent": 0}
def _get_disk(self) -> Dict[str, Any]:
if self.psutil:
try:
d = self.psutil.disk_usage('/')
return {"total_gb": round(d.total / 1073741824, 1),
"used_gb": round(d.used / 1073741824, 1),
"percent": d.percent}
except Exception:
pass
return {"total_gb": 0, "used_gb": 0, "percent": 0}
def _get_temperature(self) -> Dict[str, Any]:
if self.psutil:
try:
temps = self.psutil.sensors_temperatures()
if temps:
for name, entries in temps.items():
for e in entries:
if e.current > 0:
return {"name": e.label or name, "current": round(e.current, 1)}
except Exception:
pass
# Android fallback: read thermal zone
try:
for i in range(10):
tz = f'/sys/class/thermal/thermal_zone{i}/temp'
ttype = f'/sys/class/thermal/thermal_zone{i}/type'
if os.path.exists(tz) and os.path.exists(ttype):
with open(ttype) as f:
name = f.read().strip()
if 'cpu' in name.lower() or 'soc' in name.lower():
with open(tz) as f:
temp = int(f.read().strip()) / 1000.0
return {"name": name, "current": round(temp, 1)}
except Exception:
pass
return {"name": "", "current": 0}
def _get_process(self) -> Dict[str, Any]:
"""Current process info (PID + RSS memory)"""
pid = os.getpid()