Files
Loki/backend/app/routes/system.py
T
Michael ecadf55743 Add real-time system stats (CPU/RAM/GPU/VRAM) and fix favicon
Favicon now matches the LokiMark topbar icon instead of an unrelated
arrow glyph. New /api/system/stats endpoint (psutil + nvidia-smi)
polled every 2s and shown in the topbar next to the Ollama status.
2026-07-01 14:56:50 +02:00

53 lines
1.6 KiB
Python

"""Statistiques système temps réel : CPU, RAM, GPU/VRAM (barre supérieure)."""
from __future__ import annotations
import asyncio
import shutil
import psutil
from fastapi import APIRouter
router = APIRouter(prefix="/api/system", tags=["system"])
_NVIDIA_SMI = shutil.which("nvidia-smi")
async def _gpu_stats() -> dict | None:
"""Utilisation GPU/VRAM via nvidia-smi ; None si absent (pas de GPU NVIDIA)."""
if not _NVIDIA_SMI:
return None
try:
proc = await asyncio.create_subprocess_exec(
_NVIDIA_SMI,
"--query-gpu=utilization.gpu,memory.used,memory.total,name",
"--format=csv,noheader,nounits",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
out, _ = await asyncio.wait_for(proc.communicate(), timeout=3)
line = out.decode().strip().splitlines()[0]
util, used, total, name = (p.strip() for p in line.split(","))
return {
"name": name,
"util_pct": float(util),
"vram_used_mb": float(used),
"vram_total_mb": float(total),
}
except Exception:
return None
@router.get("/stats")
async def stats() -> dict:
"""CPU %, RAM et GPU/VRAM courants."""
cpu_pct = psutil.cpu_percent(interval=None)
mem = psutil.virtual_memory()
gpu = await _gpu_stats()
return {
"cpu_pct": cpu_pct,
"ram_used_go": round(mem.used / 1_000_000_000, 1),
"ram_total_go": round(mem.total / 1_000_000_000, 1),
"ram_pct": mem.percent,
"gpu": gpu,
}