This commit is contained in:
2025-09-10 11:46:57 -07:00
parent 2cc2b4c9ce
commit f443e7a64e
33 changed files with 887 additions and 1467 deletions

View File

@@ -1,9 +1,54 @@
from fastapi import APIRouter
from fastapi.responses import PlainTextResponse, JSONResponse
from app.services.health_monitor import HealthMonitor
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST, Gauge
from pathlib import Path
import json
router = APIRouter()
monitor = HealthMonitor()
# Prometheus metrics
SYNC_QUEUE = Gauge('sync_queue_size', 'Current Garmin sync queue size')
PENDING_ANALYSES = Gauge('pending_analyses', 'Number of pending workout analyses')
@router.get("/health")
async def get_health():
return monitor.check_system_health()
return monitor.check_system_health()
@router.get("/metrics")
async def prometheus_metrics():
# Update metrics with latest values
health_data = monitor.check_system_health()
SYNC_QUEUE.set(health_data['services'].get('sync_queue_size', 0))
PENDING_ANALYSES.set(health_data['services'].get('pending_analyses', 0))
return PlainTextResponse(
content=generate_latest(),
media_type=CONTENT_TYPE_LATEST
)
@router.get("/dashboard/health", response_class=JSONResponse)
async def health_dashboard():
"""Health dashboard endpoint with aggregated monitoring data"""
health_data = monitor.check_system_health()
# Get recent logs (last 100 lines)
log_file = Path("/app/logs/app.log")
recent_logs = []
try:
with log_file.open() as f:
lines = f.readlines()[-100:]
recent_logs = [json.loads(line.strip()) for line in lines]
except FileNotFoundError:
pass
return {
"system": health_data,
"logs": recent_logs,
"statistics": {
"log_entries": len(recent_logs),
"error_count": sum(1 for log in recent_logs if log.get('level') == 'ERROR'),
"warning_count": sum(1 for log in recent_logs if log.get('level') == 'WARNING')
}
}

View File

@@ -8,8 +8,9 @@ from app.models.workout import Workout
from app.models.analysis import Analysis
from app.models.garmin_sync_log import GarminSyncLog
from app.models.plan import Plan
from app.schemas.workout import Workout as WorkoutSchema, WorkoutSyncStatus
from app.schemas.workout import Workout as WorkoutSchema, WorkoutSyncStatus, WorkoutMetric
from app.schemas.analysis import Analysis as AnalysisSchema
from app.schemas.plan import Plan as PlanSchema
from app.services.workout_sync import WorkoutSyncService
from app.services.ai_service import AIService
from app.services.plan_evolution import PlanEvolutionService
@@ -32,7 +33,7 @@ async def read_workout(workout_id: int, db: AsyncSession = Depends(get_db)):
raise HTTPException(status_code=404, detail="Workout not found")
return workout
@router.get("/{workout_id}/metrics", response_model=list[schemas.WorkoutMetric])
@router.get("/{workout_id}/metrics", response_model=list[WorkoutMetric])
async def get_workout_metrics(
workout_id: int,
db: AsyncSession = Depends(get_db)
@@ -153,7 +154,7 @@ async def approve_analysis(
return {"message": "Analysis approved"}
@router.get("/plans/{plan_id}/evolution", response_model=List[schemas.Plan])
@router.get("/plans/{plan_id}/evolution", response_model=List[PlanSchema])
async def get_plan_evolution(
plan_id: int,
db: AsyncSession = Depends(get_db)