Files
bakery-ia/services/suppliers/app/api/analytics.py

624 lines
22 KiB
Python
Raw Normal View History

2025-10-06 15:27:01 +02:00
# services/suppliers/app/api/analytics.py
2025-08-21 20:28:14 +02:00
"""
2025-10-06 15:27:01 +02:00
Supplier Analytics API endpoints (ANALYTICS)
Consolidates performance metrics, delivery stats, and all analytics operations
2025-08-21 20:28:14 +02:00
"""
from datetime import datetime, timedelta
2025-10-06 15:27:01 +02:00
from typing import List, Optional, Dict, Any
2025-08-21 20:28:14 +02:00
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Path, status
from sqlalchemy.ext.asyncio import AsyncSession
2025-10-06 15:27:01 +02:00
from sqlalchemy.orm import Session
2025-08-21 20:28:14 +02:00
import structlog
from shared.auth.decorators import get_current_user_dep
2025-10-06 15:27:01 +02:00
from shared.auth.access_control import require_user_role, analytics_tier_required
from shared.routing import RouteBuilder
2025-08-21 20:28:14 +02:00
from app.core.database import get_db
from app.services.performance_service import PerformanceTrackingService, AlertService
from app.services.dashboard_service import DashboardService
2025-10-06 15:27:01 +02:00
from app.services.delivery_service import DeliveryService
2025-08-21 20:28:14 +02:00
from app.schemas.performance import (
2025-10-06 15:27:01 +02:00
PerformanceMetric, Alert, PerformanceDashboardSummary,
SupplierPerformanceInsights, PerformanceAnalytics, BusinessModelInsights,
AlertSummary, PerformanceReportRequest, ExportDataResponse
2025-08-21 20:28:14 +02:00
)
2025-10-06 15:27:01 +02:00
from app.schemas.suppliers import DeliveryPerformanceStats, DeliverySummaryStats
2025-08-21 20:28:14 +02:00
from app.models.performance import PerformancePeriod, PerformanceMetricType, AlertType, AlertSeverity
logger = structlog.get_logger()
2025-10-06 15:27:01 +02:00
# Create route builder for consistent URL structure
route_builder = RouteBuilder('suppliers')
router = APIRouter(tags=["analytics"])
2025-08-21 20:28:14 +02:00
# ===== Dependency Injection =====
async def get_performance_service() -> PerformanceTrackingService:
"""Get performance tracking service"""
return PerformanceTrackingService()
async def get_alert_service() -> AlertService:
"""Get alert service"""
return AlertService()
async def get_dashboard_service() -> DashboardService:
"""Get dashboard service"""
return DashboardService()
2025-10-06 15:27:01 +02:00
# ===== Delivery Analytics =====
2025-08-21 20:28:14 +02:00
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("deliveries/performance-stats"),
response_model=DeliveryPerformanceStats
)
async def get_delivery_performance_stats(
tenant_id: UUID = Path(...),
days_back: int = Query(30, ge=1, le=365, description="Number of days to analyze"),
supplier_id: Optional[UUID] = Query(None, description="Filter by supplier ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""Get delivery performance statistics"""
try:
service = DeliveryService(db)
stats = await service.get_delivery_performance_stats(
2025-10-27 16:33:26 +01:00
tenant_id=current_user["tenant_id"],
2025-10-06 15:27:01 +02:00
days_back=days_back,
supplier_id=supplier_id
)
return DeliveryPerformanceStats(**stats)
except Exception as e:
logger.error("Error getting delivery performance stats", error=str(e))
raise HTTPException(status_code=500, detail="Failed to retrieve delivery performance statistics")
@router.get(
route_builder.build_analytics_route("deliveries/summary-stats"),
response_model=DeliverySummaryStats
)
async def get_delivery_summary_stats(
tenant_id: UUID = Path(...),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""Get delivery summary statistics for dashboard"""
try:
service = DeliveryService(db)
2025-10-27 16:33:26 +01:00
stats = await service.get_upcoming_deliveries_summary(current_user["tenant_id"])
2025-10-06 15:27:01 +02:00
return DeliverySummaryStats(**stats)
except Exception as e:
logger.error("Error getting delivery summary stats", error=str(e))
raise HTTPException(status_code=500, detail="Failed to retrieve delivery summary statistics")
# ===== Performance Metrics =====
@router.post(
route_builder.build_analytics_route("performance/{supplier_id}/calculate"),
response_model=PerformanceMetric
)
2025-08-21 20:28:14 +02:00
async def calculate_supplier_performance(
tenant_id: UUID = Path(...),
supplier_id: UUID = Path(...),
period: PerformancePeriod = Query(...),
period_start: datetime = Query(...),
period_end: datetime = Query(...),
current_user: dict = Depends(get_current_user_dep),
performance_service: PerformanceTrackingService = Depends(get_performance_service),
db: AsyncSession = Depends(get_db)
):
"""Calculate performance metrics for a supplier"""
try:
metric = await performance_service.calculate_supplier_performance(
db, supplier_id, tenant_id, period, period_start, period_end
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
if not metric:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Unable to calculate performance metrics"
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Performance metrics calculated",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id),
period=period.value)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return metric
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error calculating performance metrics",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to calculate performance metrics"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/{supplier_id}/metrics"),
response_model=List[PerformanceMetric]
)
2025-08-21 20:28:14 +02:00
async def get_supplier_performance_metrics(
tenant_id: UUID = Path(...),
supplier_id: UUID = Path(...),
metric_type: Optional[PerformanceMetricType] = Query(None),
period: Optional[PerformancePeriod] = Query(None),
date_from: Optional[datetime] = Query(None),
date_to: Optional[datetime] = Query(None),
limit: int = Query(50, ge=1, le=500),
current_user: dict = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
"""Get performance metrics for a supplier"""
try:
2025-10-24 13:05:04 +02:00
from app.models.performance import SupplierPerformanceMetric
from sqlalchemy import select, and_, desc
# Build query for performance metrics
query = select(SupplierPerformanceMetric).where(
and_(
SupplierPerformanceMetric.supplier_id == supplier_id,
SupplierPerformanceMetric.tenant_id == tenant_id
)
)
# Apply filters
if metric_type:
query = query.where(SupplierPerformanceMetric.metric_type == metric_type)
if date_from:
query = query.where(SupplierPerformanceMetric.calculated_at >= date_from)
if date_to:
query = query.where(SupplierPerformanceMetric.calculated_at <= date_to)
# Order by most recent and apply limit
query = query.order_by(desc(SupplierPerformanceMetric.calculated_at)).limit(limit)
result = await db.execute(query)
metrics = result.scalars().all()
logger.info("Retrieved performance metrics",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id),
count=len(metrics))
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return metrics
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting performance metrics",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve performance metrics"
)
2025-10-06 15:27:01 +02:00
# ===== Alert Management =====
2025-08-21 20:28:14 +02:00
2025-10-06 15:27:01 +02:00
@router.post(
route_builder.build_analytics_route("performance/alerts/evaluate"),
response_model=List[Alert]
)
@require_user_role(['admin', 'owner'])
2025-08-21 20:28:14 +02:00
async def evaluate_performance_alerts(
tenant_id: UUID = Path(...),
supplier_id: Optional[UUID] = Query(None, description="Specific supplier to evaluate"),
current_user: dict = Depends(get_current_user_dep),
alert_service: AlertService = Depends(get_alert_service),
db: AsyncSession = Depends(get_db)
):
"""Evaluate and create performance-based alerts"""
try:
alerts = await alert_service.evaluate_performance_alerts(db, tenant_id, supplier_id)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Performance alerts evaluated",
tenant_id=str(tenant_id),
alerts_created=len(alerts))
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return alerts
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error evaluating performance alerts",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to evaluate performance alerts"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/alerts"),
response_model=List[Alert]
)
2025-08-21 20:28:14 +02:00
async def get_supplier_alerts(
tenant_id: UUID = Path(...),
supplier_id: Optional[UUID] = Query(None),
alert_type: Optional[AlertType] = Query(None),
severity: Optional[AlertSeverity] = Query(None),
date_from: Optional[datetime] = Query(None),
date_to: Optional[datetime] = Query(None),
limit: int = Query(50, ge=1, le=500),
current_user: dict = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
"""Get supplier alerts with filtering"""
try:
2025-10-24 13:05:04 +02:00
from app.models.performance import SupplierAlert
from sqlalchemy import select, and_, desc
# Build query for alerts
query = select(SupplierAlert).where(
SupplierAlert.tenant_id == tenant_id
)
# Apply filters
if supplier_id:
query = query.where(SupplierAlert.supplier_id == supplier_id)
if alert_type:
query = query.where(SupplierAlert.alert_type == alert_type)
if severity:
query = query.where(SupplierAlert.severity == severity)
if date_from:
query = query.where(SupplierAlert.created_at >= date_from)
if date_to:
query = query.where(SupplierAlert.created_at <= date_to)
# Order by most recent and apply limit
query = query.order_by(desc(SupplierAlert.created_at)).limit(limit)
result = await db.execute(query)
alerts = result.scalars().all()
logger.info("Retrieved supplier alerts",
tenant_id=str(tenant_id),
count=len(alerts))
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return alerts
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting supplier alerts",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve supplier alerts"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/alerts/summary"),
response_model=List[AlertSummary]
)
async def get_alert_summary(
2025-08-21 20:28:14 +02:00
tenant_id: UUID = Path(...),
2025-10-06 15:27:01 +02:00
date_from: Optional[datetime] = Query(None),
date_to: Optional[datetime] = Query(None),
2025-08-21 20:28:14 +02:00
current_user: dict = Depends(get_current_user_dep),
2025-10-06 15:27:01 +02:00
dashboard_service: DashboardService = Depends(get_dashboard_service),
2025-08-21 20:28:14 +02:00
db: AsyncSession = Depends(get_db)
):
2025-10-06 15:27:01 +02:00
"""Get alert summary by type and severity"""
2025-08-21 20:28:14 +02:00
try:
2025-10-06 15:27:01 +02:00
summary = await dashboard_service.get_alert_summary(db, tenant_id, date_from, date_to)
return summary
2025-08-21 20:28:14 +02:00
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting alert summary",
2025-08-21 20:28:14 +02:00
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2025-10-06 15:27:01 +02:00
detail="Failed to retrieve alert summary"
2025-08-21 20:28:14 +02:00
)
2025-10-06 15:27:01 +02:00
# ===== Dashboard Analytics =====
2025-08-21 20:28:14 +02:00
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_dashboard_route("performance/summary"),
response_model=PerformanceDashboardSummary
)
2025-08-21 20:28:14 +02:00
async def get_performance_dashboard_summary(
tenant_id: UUID = Path(...),
date_from: Optional[datetime] = Query(None),
date_to: Optional[datetime] = Query(None),
current_user: dict = Depends(get_current_user_dep),
dashboard_service: DashboardService = Depends(get_dashboard_service),
db: AsyncSession = Depends(get_db)
):
"""Get comprehensive performance dashboard summary"""
try:
summary = await dashboard_service.get_performance_dashboard_summary(
db, tenant_id, date_from, date_to
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Performance dashboard summary retrieved",
tenant_id=str(tenant_id))
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return summary
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting dashboard summary",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve dashboard summary"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/{supplier_id}/insights"),
response_model=SupplierPerformanceInsights
)
2025-08-21 20:28:14 +02:00
async def get_supplier_performance_insights(
tenant_id: UUID = Path(...),
supplier_id: UUID = Path(...),
days_back: int = Query(30, ge=1, le=365),
current_user: dict = Depends(get_current_user_dep),
dashboard_service: DashboardService = Depends(get_dashboard_service),
db: AsyncSession = Depends(get_db)
):
"""Get detailed performance insights for a specific supplier"""
try:
insights = await dashboard_service.get_supplier_performance_insights(
db, tenant_id, supplier_id, days_back
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Supplier performance insights retrieved",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id))
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return insights
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting supplier insights",
tenant_id=str(tenant_id),
supplier_id=str(supplier_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve supplier insights"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/performance"),
response_model=PerformanceAnalytics
)
@analytics_tier_required
2025-08-21 20:28:14 +02:00
async def get_performance_analytics(
tenant_id: UUID = Path(...),
period_days: int = Query(90, ge=1, le=365),
current_user: dict = Depends(get_current_user_dep),
dashboard_service: DashboardService = Depends(get_dashboard_service),
db: AsyncSession = Depends(get_db)
):
"""Get advanced performance analytics"""
try:
analytics = await dashboard_service.get_performance_analytics(
db, tenant_id, period_days
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Performance analytics retrieved",
tenant_id=str(tenant_id),
period_days=period_days)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return analytics
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting performance analytics",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve performance analytics"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/business-model"),
response_model=BusinessModelInsights
)
@analytics_tier_required
2025-08-21 20:28:14 +02:00
async def get_business_model_insights(
tenant_id: UUID = Path(...),
current_user: dict = Depends(get_current_user_dep),
dashboard_service: DashboardService = Depends(get_dashboard_service),
db: AsyncSession = Depends(get_db)
):
"""Get business model detection and insights"""
try:
insights = await dashboard_service.get_business_model_insights(db, tenant_id)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
logger.info("Business model insights retrieved",
tenant_id=str(tenant_id),
detected_model=insights.detected_model)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return insights
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting business model insights",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve business model insights"
)
2025-10-06 15:27:01 +02:00
# ===== Export and Reporting =====
2025-08-21 20:28:14 +02:00
2025-10-06 15:27:01 +02:00
@router.post(
route_builder.build_analytics_route("performance/reports/generate"),
response_model=ExportDataResponse
)
@require_user_role(['admin', 'owner'])
2025-08-21 20:28:14 +02:00
async def generate_performance_report(
report_request: PerformanceReportRequest,
tenant_id: UUID = Path(...),
current_user: dict = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
"""Generate a performance report"""
try:
# TODO: Implement report generation
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="Report generation not yet implemented"
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error generating performance report",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to generate performance report"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/export")
)
2025-08-21 20:28:14 +02:00
async def export_performance_data(
tenant_id: UUID = Path(...),
format: str = Query("json", description="Export format: json, csv, excel"),
date_from: Optional[datetime] = Query(None),
date_to: Optional[datetime] = Query(None),
supplier_ids: Optional[List[UUID]] = Query(None),
current_user: dict = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
"""Export performance data"""
try:
if format.lower() not in ["json", "csv", "excel"]:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Unsupported export format. Use: json, csv, excel"
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# TODO: Implement data export
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="Data export not yet implemented"
)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error exporting performance data",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to export performance data"
)
2025-10-06 15:27:01 +02:00
# ===== Configuration and Health =====
2025-08-21 20:28:14 +02:00
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/config")
)
2025-08-21 20:28:14 +02:00
async def get_performance_config(
tenant_id: UUID = Path(...),
current_user: dict = Depends(get_current_user_dep)
):
"""Get performance tracking configuration"""
try:
from app.core.config import settings
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
config = {
"performance_tracking": {
"enabled": settings.PERFORMANCE_TRACKING_ENABLED,
"calculation_interval_minutes": settings.PERFORMANCE_CALCULATION_INTERVAL_MINUTES,
"cache_ttl_seconds": settings.PERFORMANCE_CACHE_TTL
},
"thresholds": {
"excellent_delivery_rate": settings.EXCELLENT_DELIVERY_RATE,
"good_delivery_rate": settings.GOOD_DELIVERY_RATE,
"acceptable_delivery_rate": settings.ACCEPTABLE_DELIVERY_RATE,
"poor_delivery_rate": settings.POOR_DELIVERY_RATE,
"excellent_quality_rate": settings.EXCELLENT_QUALITY_RATE,
"good_quality_rate": settings.GOOD_QUALITY_RATE,
"acceptable_quality_rate": settings.ACCEPTABLE_QUALITY_RATE,
"poor_quality_rate": settings.POOR_QUALITY_RATE
},
"alerts": {
"enabled": settings.ALERTS_ENABLED,
"evaluation_interval_minutes": settings.ALERT_EVALUATION_INTERVAL_MINUTES,
"retention_days": settings.ALERT_RETENTION_DAYS,
"critical_delivery_delay_hours": settings.CRITICAL_DELIVERY_DELAY_HOURS,
"critical_quality_rejection_rate": settings.CRITICAL_QUALITY_REJECTION_RATE
},
"dashboard": {
"cache_ttl_seconds": settings.DASHBOARD_CACHE_TTL,
"refresh_interval_seconds": settings.DASHBOARD_REFRESH_INTERVAL,
"default_analytics_period_days": settings.DEFAULT_ANALYTICS_PERIOD_DAYS
},
"business_model": {
"detection_enabled": settings.ENABLE_BUSINESS_MODEL_DETECTION,
"central_bakery_threshold": settings.CENTRAL_BAKERY_THRESHOLD_SUPPLIERS,
"individual_bakery_threshold": settings.INDIVIDUAL_BAKERY_THRESHOLD_SUPPLIERS
}
}
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
return config
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting performance config",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve performance configuration"
)
2025-10-06 15:27:01 +02:00
@router.get(
route_builder.build_analytics_route("performance/health")
)
2025-08-21 20:28:14 +02:00
async def get_performance_health(
tenant_id: UUID = Path(...),
current_user: dict = Depends(get_current_user_dep)
):
"""Get performance service health status"""
try:
return {
"service": "suppliers-performance",
"status": "healthy",
"timestamp": datetime.now().isoformat(),
"tenant_id": str(tenant_id),
"features": {
"performance_tracking": "enabled",
"alerts": "enabled",
"dashboard_analytics": "enabled",
"business_model_detection": "enabled"
}
}
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
except Exception as e:
logger.error("Error getting performance health",
tenant_id=str(tenant_id),
error=str(e))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to get performance health status"
2025-10-06 15:27:01 +02:00
)