fishapi / app /api /v1 /endpoints /health.py
kamau1's picture
Initial commit
bcc2f7b verified
"""
Health check and system status endpoints.
"""
from datetime import datetime
from fastapi import APIRouter, HTTPException, status
from app.models.inference import HealthResponse, APIInfo, ModelInfo, ErrorResponse
from app.services.model_service import model_service
from app.core.config import settings
from app.core.logging import get_logger
logger = get_logger(__name__)
router = APIRouter()
@router.get(
"/health",
response_model=HealthResponse,
summary="Health Check",
description="Check the health status of the API and model"
)
async def health_check() -> HealthResponse:
"""
Perform a comprehensive health check of the API and model.
Returns the current status of the API, model loading status, and basic model information.
This endpoint can be used for monitoring and load balancer health checks.
"""
try:
logger.debug("Performing health check")
# Check model health
health_status = await model_service.health_check()
model_info = None
if health_status.get("model_loaded", False):
model_info_dict = health_status.get("model_info", {})
if model_info_dict:
model_info = ModelInfo(**model_info_dict)
return HealthResponse(
status="healthy" if health_status.get("model_loaded", False) else "degraded",
model_loaded=health_status.get("model_loaded", False),
model_info=model_info,
timestamp=datetime.utcnow().isoformat()
)
except Exception as e:
logger.error(f"Health check failed: {str(e)}")
return HealthResponse(
status="unhealthy",
model_loaded=False,
model_info=None,
timestamp=datetime.utcnow().isoformat()
)
@router.get(
"/info",
response_model=APIInfo,
summary="API Information",
description="Get comprehensive information about the API and model"
)
async def get_api_info() -> APIInfo:
"""
Get comprehensive information about the API.
Returns detailed information about the API version, capabilities, model information,
and available endpoints.
"""
try:
logger.debug("Fetching API information")
# Get model information
model_info_dict = model_service.get_model_info()
model_info = ModelInfo(**model_info_dict)
# Define available endpoints
endpoints = [
f"{settings.API_V1_STR}/detect",
f"{settings.API_V1_STR}/species",
f"{settings.API_V1_STR}/species/{{class_id}}",
f"{settings.API_V1_STR}/health",
f"{settings.API_V1_STR}/info"
]
return APIInfo(
name=settings.PROJECT_NAME,
version=settings.VERSION,
description=settings.DESCRIPTION,
model_info=model_info,
endpoints=endpoints
)
except Exception as e:
logger.error(f"Failed to get API info: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get API information: {str(e)}"
)
@router.get(
"/ready",
summary="Readiness Check",
description="Check if the API is ready to serve requests"
)
async def readiness_check() -> dict:
"""
Check if the API is ready to serve requests.
This endpoint is specifically designed for Kubernetes readiness probes.
It returns 200 OK only when the model is loaded and ready to process requests.
"""
try:
health_status = await model_service.health_check()
if health_status.get("model_loaded", False):
return {"status": "ready"}
else:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Model not ready"
)
except HTTPException:
raise
except Exception as e:
logger.error(f"Readiness check failed: {str(e)}")
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Service not ready"
)
@router.get(
"/live",
summary="Liveness Check",
description="Check if the API is alive"
)
async def liveness_check() -> dict:
"""
Check if the API is alive.
This endpoint is designed for Kubernetes liveness probes.
It performs a minimal check to ensure the API process is running.
"""
return {"status": "alive", "timestamp": datetime.utcnow().isoformat()}