122 lines
4.6 KiB
Python
122 lines
4.6 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional, List, Dict, Any
|
|
|
|
from sqlalchemy import select, delete, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.host_metrics import HostMetrics
|
|
|
|
|
|
class HostMetricsRepository:
|
|
"""Repository pour gérer les métriques des hôtes"""
|
|
|
|
def __init__(self, session: AsyncSession):
|
|
self.session = session
|
|
|
|
async def create(self, **fields) -> HostMetrics:
|
|
"""Crée une nouvelle entrée de métriques"""
|
|
metrics = HostMetrics(**fields)
|
|
self.session.add(metrics)
|
|
await self.session.flush()
|
|
return metrics
|
|
|
|
async def get(self, metrics_id: int) -> Optional[HostMetrics]:
|
|
"""Récupère une entrée de métriques par son ID"""
|
|
stmt = select(HostMetrics).where(HostMetrics.id == metrics_id)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def get_latest_for_host(self, host_id: str, metric_type: str = None) -> Optional[HostMetrics]:
|
|
"""Récupère les dernières métriques pour un hôte"""
|
|
stmt = select(HostMetrics).where(HostMetrics.host_id == host_id)
|
|
if metric_type:
|
|
stmt = stmt.where(HostMetrics.metric_type == metric_type)
|
|
stmt = stmt.order_by(HostMetrics.collected_at.desc()).limit(1)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def list_for_host(
|
|
self,
|
|
host_id: str,
|
|
metric_type: str = None,
|
|
limit: int = 100,
|
|
offset: int = 0
|
|
) -> List[HostMetrics]:
|
|
"""Liste les métriques pour un hôte avec pagination"""
|
|
stmt = select(HostMetrics).where(HostMetrics.host_id == host_id)
|
|
if metric_type:
|
|
stmt = stmt.where(HostMetrics.metric_type == metric_type)
|
|
stmt = stmt.order_by(HostMetrics.collected_at.desc()).offset(offset).limit(limit)
|
|
result = await self.session.execute(stmt)
|
|
return list(result.scalars().all())
|
|
|
|
async def get_all_latest(self, metric_type: str = "system_info") -> Dict[str, HostMetrics]:
|
|
"""Récupère les dernières métriques pour tous les hôtes
|
|
|
|
Returns:
|
|
Dict mapping host_id to latest HostMetrics
|
|
"""
|
|
# Sous-requête pour obtenir la date max par host_id
|
|
subq = (
|
|
select(
|
|
HostMetrics.host_id,
|
|
func.max(HostMetrics.collected_at).label("max_collected")
|
|
)
|
|
.where(HostMetrics.metric_type == metric_type)
|
|
.group_by(HostMetrics.host_id)
|
|
.subquery()
|
|
)
|
|
|
|
# Jointure pour récupérer les enregistrements complets
|
|
stmt = (
|
|
select(HostMetrics)
|
|
.join(
|
|
subq,
|
|
(HostMetrics.host_id == subq.c.host_id) &
|
|
(HostMetrics.collected_at == subq.c.max_collected)
|
|
)
|
|
.where(HostMetrics.metric_type == metric_type)
|
|
)
|
|
|
|
result = await self.session.execute(stmt)
|
|
metrics_list = result.scalars().all()
|
|
|
|
return {m.host_id: m for m in metrics_list}
|
|
|
|
async def cleanup_old_metrics(self, days_to_keep: int = 30) -> int:
|
|
"""Supprime les métriques plus anciennes que le nombre de jours spécifié
|
|
|
|
Returns:
|
|
Nombre d'entrées supprimées
|
|
"""
|
|
cutoff_date = datetime.utcnow() - timedelta(days=days_to_keep)
|
|
stmt = delete(HostMetrics).where(HostMetrics.collected_at < cutoff_date)
|
|
result = await self.session.execute(stmt)
|
|
return result.rowcount
|
|
|
|
async def get_metrics_history(
|
|
self,
|
|
host_id: str,
|
|
metric_type: str = "system_info",
|
|
hours: int = 24
|
|
) -> List[HostMetrics]:
|
|
"""Récupère l'historique des métriques pour les dernières heures"""
|
|
cutoff = datetime.utcnow() - timedelta(hours=hours)
|
|
stmt = (
|
|
select(HostMetrics)
|
|
.where(HostMetrics.host_id == host_id)
|
|
.where(HostMetrics.metric_type == metric_type)
|
|
.where(HostMetrics.collected_at >= cutoff)
|
|
.order_by(HostMetrics.collected_at.asc())
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return list(result.scalars().all())
|
|
|
|
async def count_for_host(self, host_id: str) -> int:
|
|
"""Compte le nombre d'entrées de métriques pour un hôte"""
|
|
stmt = select(func.count(HostMetrics.id)).where(HostMetrics.host_id == host_id)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar() or 0
|