Feat : Better stats
Some checks failed
Build and Push Docker Images / docker (push) Failing after 7s

This commit is contained in:
jeanotx32
2026-05-18 23:54:44 -04:00
parent c7cc18101a
commit 3080826806
7 changed files with 476 additions and 6 deletions

View File

@@ -9,6 +9,7 @@ import json
import os
import secrets
import sqlite3
from collections import deque
from contextlib import contextmanager
from datetime import datetime, timedelta, timezone
from pathlib import Path
@@ -25,6 +26,10 @@ from pydantic import BaseModel
# ─── Config ───────────────────────────────────────────────────────────────────
DB_FILE = Path(os.getenv("DB_FILE", "data/monitor.db"))
# ─── Ring buffer de stats (en mémoire) ───────────────────────────────────────
_STATS_MAX_POINTS = 120 # 10 min à 5 s d'intervalle
_stats_history: dict[str, deque] = {}
SECRET_FILE = Path(os.getenv("SECRET_FILE", "data/.jwt_secret"))
AGENT_TIMEOUT = int(os.getenv("AGENT_TIMEOUT", "5"))
JWT_ALGORITHM = "HS256"
@@ -279,6 +284,45 @@ async def fetch_vps_status(vps: dict) -> dict:
}
# ─── Collecteur de stats (tâche de fond) ─────────────────────────────────────
async def _fetch_system_stat(vps: dict) -> None:
"""Collecte un point de stats système pour un VPS et l'insère dans le ring buffer."""
try:
data = await agent_get(vps, "/system")
buf = _stats_history.setdefault(vps["id"], deque(maxlen=_STATS_MAX_POINTS))
buf.append({
"ts": datetime.now(timezone.utc).isoformat(),
"cpu": data["cpu_percent"],
"ram_percent": data["ram_percent"],
"ram_used": data["ram_used"],
"ram_total": data["ram_total"],
"net_sent_per_sec": data["net_sent_per_sec"],
"net_recv_per_sec": data["net_recv_per_sec"],
"net_bytes_sent": data.get("net_bytes_sent", 0),
"net_bytes_recv": data.get("net_bytes_recv", 0),
})
except Exception:
pass # VPS hors ligne ou agent non mis à jour — ignoré silencieusement
async def _stats_collector() -> None:
"""Tâche de fond : collecte les stats de tous les VPS toutes les 5 secondes."""
await asyncio.sleep(3) # laisse l'app finir de démarrer
while True:
vps_list = load_vps()
await asyncio.gather(
*[_fetch_system_stat(v) for v in vps_list],
return_exceptions=True,
)
await asyncio.sleep(5)
@app.on_event("startup")
async def startup_event() -> None:
asyncio.create_task(_stats_collector())
# ─── Routes Auth ──────────────────────────────────────────────────────────────
@app.get("/api/auth/status")
@@ -370,6 +414,14 @@ def edit_vps(vps_id: str, body: VpsUpdateRequest, _: Annotated[dict, Depends(get
return {"status": "ok"}
@app.get("/api/vps/{vps_id}/stats")
def get_vps_stats(vps_id: str, _: Annotated[dict, Depends(get_current_user)]):
"""Retourne l'historique des stats système d'un VPS (ring buffer en mémoire)."""
if not any(v["id"] == vps_id for v in load_vps()):
raise HTTPException(status_code=404, detail="VPS introuvable")
return list(_stats_history.get(vps_id, deque()))
@app.get("/api/status")
async def all_status(_: Annotated[dict, Depends(get_current_user)]):
"""Retourne l'état de tous les VPS en parallèle."""