"""Health check and status endpoints.""" from fastapi import APIRouter, HTTPException from pydantic import BaseModel import logging import httpx from datetime import datetime from app.config import settings logger = logging.getLogger(__name__) router = APIRouter() class ServiceStatus(BaseModel): service: str status: str # "ok", "degraded", "error" latency_ms: float error: str = None class HealthResponse(BaseModel): timestamp: str services: dict[str, ServiceStatus] overall_status: str @router.get("/health", response_model=HealthResponse) async def health_check(): """Check health of all dependencies.""" services = {} overall_ok = True # Check PostgreSQL try: # Simple connection test from app.db import engine if engine: async with engine.connect() as conn: start = datetime.utcnow() await conn.execute("SELECT 1") latency = (datetime.utcnow() - start).total_seconds() * 1000 services["postgresql"] = ServiceStatus( service="postgresql", status="ok", latency_ms=latency ) else: services["postgresql"] = ServiceStatus( service="postgresql", status="error", latency_ms=0, error="Not initialized" ) overall_ok = False except Exception as e: services["postgresql"] = ServiceStatus( service="postgresql", status="error", latency_ms=0, error=str(e) ) overall_ok = False # Check Qdrant try: start = datetime.utcnow() async with httpx.AsyncClient() as client: resp = await client.get(f"{settings.QDRANT_URL}/health") latency = (datetime.utcnow() - start).total_seconds() * 1000 if resp.status_code == 200: services["qdrant"] = ServiceStatus( service="qdrant", status="ok", latency_ms=latency ) else: services["qdrant"] = ServiceStatus( service="qdrant", status="error", latency_ms=latency, error=f"HTTP {resp.status_code}" ) overall_ok = False except Exception as e: services["qdrant"] = ServiceStatus( service="qdrant", status="error", latency_ms=0, error=str(e) ) overall_ok = False # Check LLM backend try: start = datetime.utcnow() if settings.LLM_BACKEND == "ollama": async with httpx.AsyncClient(timeout=5) as client: resp = await client.get(f"{settings.OLLAMA_URL}/api/tags") latency = (datetime.utcnow() - start).total_seconds() * 1000 if resp.status_code == 200: services["llm_backend"] = ServiceStatus( service=f"ollama ({settings.OLLAMA_MODEL})", status="ok", latency_ms=latency ) else: services["llm_backend"] = ServiceStatus( service="ollama", status="error", latency_ms=latency, error=f"HTTP {resp.status_code}" ) overall_ok = False except Exception as e: services["llm_backend"] = ServiceStatus( service="llm_backend", status="error", latency_ms=0, error=str(e) ) overall_ok = False return HealthResponse( timestamp=datetime.utcnow().isoformat(), services=services, overall_status="ok" if overall_ok else "error" ) @router.get("/status") async def status(): """Get sidecar status and configuration.""" return { "service": "LightRAG Sidecar", "domain": settings.LIGHTRAG_DOMAIN, "llm_backend": settings.LLM_BACKEND, "embedding_model": settings.EMBEDDING_MODEL, "vector_size": 384, "retrieval_weights": settings.HYBRID_RETRIEVAL_WEIGHTS, "port": settings.LIGHTRAG_PORT, "environment": settings.ENVIRONMENT }