Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
161 lines
5.6 KiB
Python
161 lines
5.6 KiB
Python
"""
|
|
Routes API pour les métriques système et des hôtes.
|
|
"""
|
|
|
|
from datetime import timezone
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
import pytz
|
|
|
|
from app.core.dependencies import get_db, verify_api_key
|
|
from app.core.config import settings
|
|
|
|
|
|
from app.crud.host_metrics import HostMetricsRepository
|
|
from app.crud.app_setting import AppSettingRepository
|
|
from app.services import db
|
|
|
|
|
|
class CollectionScheduleRequest(BaseModel):
|
|
interval: str = "off"
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def _to_app_timezone(dt):
|
|
if dt is None:
|
|
return None
|
|
if getattr(dt, "tzinfo", None) is None:
|
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
tz = pytz.timezone(settings.scheduler_timezone)
|
|
return dt.astimezone(tz)
|
|
|
|
|
|
@router.get("")
|
|
async def get_metrics(api_key_valid: bool = Depends(verify_api_key)):
|
|
"""Récupère les métriques système globales."""
|
|
return db.metrics
|
|
|
|
|
|
@router.get("/all-hosts")
|
|
async def get_all_hosts_metrics(
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Récupère les métriques de tous les hôtes."""
|
|
try:
|
|
repo = HostMetricsRepository(db_session)
|
|
metrics_dict = await repo.get_all_latest()
|
|
|
|
# Convertir en dict host_id -> metrics
|
|
result = {}
|
|
for host_id, m in metrics_dict.items():
|
|
collected_at = _to_app_timezone(m.collected_at)
|
|
result[m.host_id] = {
|
|
"host_id": m.host_id,
|
|
"metric_type": m.metric_type,
|
|
"cpu_usage_percent": m.cpu_usage_percent,
|
|
"cpu_load_1m": m.cpu_load_1m,
|
|
"cpu_model": m.cpu_model,
|
|
"cpu_count": m.cpu_count,
|
|
"memory_usage_percent": m.memory_usage_percent,
|
|
"memory_total_mb": m.memory_total_mb,
|
|
"memory_used_mb": m.memory_used_mb,
|
|
"disk_root_usage_percent": m.disk_root_usage_percent,
|
|
"disk_root_total_gb": m.disk_root_total_gb,
|
|
"disk_root_used_gb": m.disk_root_used_gb,
|
|
"os_name": m.os_name,
|
|
"uptime_human": m.uptime_human,
|
|
"last_collected": collected_at,
|
|
"collected_at": collected_at,
|
|
"collection_status": "success" if not m.error_message else "failed",
|
|
"error_message": m.error_message,
|
|
}
|
|
return result
|
|
except Exception as e:
|
|
# Si la table n'existe pas encore ou autre erreur
|
|
return {}
|
|
|
|
|
|
@router.get("/collection-schedule")
|
|
async def get_collection_schedule(
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Récupère l'intervalle de collecte des métriques."""
|
|
try:
|
|
repo = AppSettingRepository(db_session)
|
|
setting = await repo.get("metrics_collection_interval")
|
|
interval = setting.value if setting else "off"
|
|
return {"interval": interval}
|
|
except Exception:
|
|
return {"interval": "off"}
|
|
|
|
|
|
@router.post("/collection-schedule")
|
|
async def set_collection_schedule(
|
|
request: CollectionScheduleRequest,
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Définit l'intervalle de collecte des métriques."""
|
|
interval = request.interval
|
|
valid_intervals = ["off", "5min", "15min", "30min", "1h", "6h", "12h", "24h"]
|
|
if interval not in valid_intervals:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Intervalle invalide. Valeurs acceptées: {valid_intervals}"
|
|
)
|
|
|
|
try:
|
|
repo = AppSettingRepository(db_session)
|
|
await repo.set("metrics_collection_interval", interval)
|
|
await db_session.commit()
|
|
return {"interval": interval, "message": f"Intervalle de collecte défini à {interval}"}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/{host_id}")
|
|
async def get_host_metrics(
|
|
host_id: str,
|
|
api_key_valid: bool = Depends(verify_api_key),
|
|
db_session: AsyncSession = Depends(get_db)
|
|
):
|
|
"""Récupère les métriques d'un hôte spécifique."""
|
|
try:
|
|
repo = HostMetricsRepository(db_session)
|
|
metrics = await repo.get_latest_for_host(host_id)
|
|
|
|
if not metrics:
|
|
return {"host_id": host_id, "collection_status": "no_data"}
|
|
|
|
collected_at = _to_app_timezone(metrics.collected_at)
|
|
|
|
return {
|
|
"host_id": metrics.host_id,
|
|
"metric_type": metrics.metric_type,
|
|
"cpu_usage_percent": metrics.cpu_usage_percent,
|
|
"cpu_load_1m": metrics.cpu_load_1m,
|
|
"cpu_model": metrics.cpu_model,
|
|
"cpu_count": metrics.cpu_count,
|
|
"memory_usage_percent": metrics.memory_usage_percent,
|
|
"memory_total_mb": metrics.memory_total_mb,
|
|
"memory_used_mb": metrics.memory_used_mb,
|
|
"disk_root_usage_percent": metrics.disk_root_usage_percent,
|
|
"disk_root_total_gb": metrics.disk_root_total_gb,
|
|
"disk_root_used_gb": metrics.disk_root_used_gb,
|
|
"disk_info": metrics.disk_info,
|
|
"os_name": metrics.os_name,
|
|
"uptime_human": metrics.uptime_human,
|
|
"last_collected": collected_at,
|
|
"collected_at": collected_at,
|
|
"collection_status": "success" if not metrics.error_message else "failed",
|
|
"error_message": metrics.error_message,
|
|
}
|
|
except Exception as e:
|
|
return {"host_id": host_id, "collection_status": "error", "error_message": str(e)}
|