from __future__ import annotations import json from datetime import datetime from typing import Any, Dict, Optional from sqlalchemy.orm import Session from models.performance_metric import PerformanceMetric class MetricsService: def __init__(self, db: Session): self.db = db def store_metric( self, metric_name: str, value: float, labels: Optional[Dict[str, Any]] = None, endpoint: Optional[str] = None, method: Optional[str] = None, status_code: Optional[int] = None, duration_seconds: Optional[float] = None, ) -> PerformanceMetric: """Store a performance metric in the database.""" metric = PerformanceMetric( timestamp=datetime.utcnow(), metric_name=metric_name, value=value, labels=json.dumps(labels) if labels else None, endpoint=endpoint, method=method, status_code=status_code, duration_seconds=duration_seconds, ) self.db.add(metric) self.db.commit() self.db.refresh(metric) return metric def get_metrics( self, metric_name: Optional[str] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, limit: int = 100, ) -> list[PerformanceMetric]: """Retrieve stored metrics with optional filtering.""" query = self.db.query(PerformanceMetric) if metric_name: query = query.filter(PerformanceMetric.metric_name == metric_name) if start_time: query = query.filter(PerformanceMetric.timestamp >= start_time) if end_time: query = query.filter(PerformanceMetric.timestamp <= end_time) return query.order_by(PerformanceMetric.timestamp.desc()).limit(limit).all() def get_aggregated_metrics( self, metric_name: str, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, ) -> Dict[str, Any]: """Get aggregated statistics for a metric.""" query = self.db.query(PerformanceMetric).filter( PerformanceMetric.metric_name == metric_name ) if start_time: query = query.filter(PerformanceMetric.timestamp >= start_time) if end_time: query = query.filter(PerformanceMetric.timestamp <= end_time) metrics = query.all() if not metrics: return {"count": 0, "avg": 0, "min": 0, "max": 0} values = [m.value for m in metrics] return { "count": len(values), "avg": sum(values) / len(values), "min": min(values), "max": max(values), } def get_metrics_service(db: Session) -> MetricsService: return MetricsService(db)