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.
This commit is contained in:
Michael committed 2026-07-01 14:56:50 +02:00
1 parent b9bccac4ba
commit ecadf55743
8 files changed
+120 -7

No files matched your search

+2 -1
View File
@@ -14,7 +14,7 @@ from fastapi.staticfiles import StaticFiles
from . import db
from .config import settings
from .routes import chat, config, files, models, sessions, shell
from .routes import chat, config, files, models, sessions, shell, system
@asynccontextmanager
@@ -42,6 +42,7 @@ app.include_router(chat.router)
app.include_router(files.router)
app.include_router(config.router)
app.include_router(shell.router)
app.include_router(system.router)
@app.get("/api/health")
+52
View File
@@ -0,0 +1,52 @@
"""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,
}
+1
View File
@@ -3,3 +3,4 @@ uvicorn[standard]==0.34.0
httpx==0.28.1
pydantic==2.10.4
pydantic-settings==2.7.1
psutil==6.1.1