Feat : Better stats
Some checks failed
Build and Push Docker Images / docker (push) Failing after 7s
Some checks failed
Build and Push Docker Images / docker (push) Failing after 7s
This commit is contained in:
@@ -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."""
|
||||
|
||||
Reference in New Issue
Block a user