bookmyservice-mhs / app /api /health.py
MukeshKapoor25's picture
feat(config): Implement centralized configuration management system
851444b
"""
Health check endpoints for monitoring application and database status.
"""
from fastapi import APIRouter, HTTPException
from typing import Dict, Any
import logging
from datetime import datetime
from app.nosql import check_mongodb_health, check_redis_health
from app.config.config import settings
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/health")
async def health_check() -> Dict[str, Any]:
"""
Basic health check endpoint.
Returns 200 if the application is running.
"""
return {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"service": "merchant-api",
"version": "1.0.0"
}
@router.get("/startup-status")
async def startup_status() -> Dict[str, Any]:
"""
Get application startup status and initialization results.
"""
try:
from app.startup import startup_manager
if startup_manager.startup_completed:
return {
"status": "completed",
"startup_completed": True,
"message": "Application initialization completed successfully"
}
else:
return {
"status": "in_progress",
"startup_completed": False,
"message": "Application initialization in progress"
}
except Exception as e:
return {
"status": "error",
"startup_completed": False,
"error": str(e),
"message": "Error checking startup status"
}
@router.get("/ready")
async def readiness_check() -> Dict[str, Any]:
"""
Readiness check endpoint.
Returns 200 if the application is ready to serve requests (databases are accessible).
"""
try:
# Check database connections
mongodb_healthy = await check_mongodb_health()
redis_healthy = await check_redis_health()
if mongodb_healthy and redis_healthy:
return {
"status": "ready",
"timestamp": datetime.utcnow().isoformat(),
"databases": {
"mongodb": "healthy",
"redis": "healthy"
}
}
else:
# Return 503 Service Unavailable if databases are not healthy
raise HTTPException(
status_code=503,
detail={
"status": "not_ready",
"timestamp": datetime.utcnow().isoformat(),
"databases": {
"mongodb": "healthy" if mongodb_healthy else "unhealthy",
"redis": "healthy" if redis_healthy else "unhealthy"
}
}
)
except Exception as e:
logger.error(f"Readiness check failed: {e}")
raise HTTPException(
status_code=503,
detail={
"status": "not_ready",
"timestamp": datetime.utcnow().isoformat(),
"error": "Database connectivity check failed"
}
)
@router.get("/status")
async def detailed_status() -> Dict[str, Any]:
"""
Detailed status endpoint for monitoring.
Provides comprehensive application status without exposing sensitive information.
"""
try:
# Check database connections
mongodb_healthy = await check_mongodb_health()
redis_healthy = await check_redis_health()
# Get system information (non-sensitive)
try:
import psutil
import os
status = {
"status": "operational" if (mongodb_healthy and redis_healthy) else "degraded",
"timestamp": datetime.utcnow().isoformat(),
"service": {
"name": "merchant-api",
"version": "1.0.0",
"environment": settings.ENVIRONMENT,
"uptime_seconds": psutil.Process().create_time()
},
"databases": {
"mongodb": {
"status": "healthy" if mongodb_healthy else "unhealthy",
"type": "document_store"
},
"redis": {
"status": "healthy" if redis_healthy else "unhealthy",
"type": "cache"
}
},
"system": {
"cpu_percent": psutil.cpu_percent(interval=1),
"memory_percent": psutil.virtual_memory().percent,
"disk_percent": psutil.disk_usage('/').percent
}
}
except ImportError:
# Fallback if psutil is not available
status = {
"status": "operational" if (mongodb_healthy and redis_healthy) else "degraded",
"timestamp": datetime.utcnow().isoformat(),
"service": {
"name": "merchant-api",
"version": "1.0.0",
"environment": settings.ENVIRONMENT
},
"databases": {
"mongodb": {
"status": "healthy" if mongodb_healthy else "unhealthy",
"type": "document_store"
},
"redis": {
"status": "healthy" if redis_healthy else "unhealthy",
"type": "cache"
}
}
}
return status
except Exception as e:
logger.error(f"Status check failed: {e}")
return {
"status": "error",
"timestamp": datetime.utcnow().isoformat(),
"error": "Status check failed"
}
@router.get("/metrics")
async def metrics() -> Dict[str, Any]:
"""
Basic metrics endpoint for monitoring systems.
Returns application metrics without sensitive data.
"""
try:
from app.utils.performance_monitor import get_performance_report
# Get performance metrics
performance_report = get_performance_report()
# Get database status
mongodb_healthy = await check_mongodb_health()
redis_healthy = await check_redis_health()
metrics = {
"timestamp": datetime.utcnow().isoformat(),
"performance": performance_report,
"database_health": {
"mongodb_healthy": mongodb_healthy,
"redis_healthy": redis_healthy
},
"request_count": performance_report.get("metrics", {}).get("total_queries", 0),
"average_response_time": performance_report.get("metrics", {}).get("average_time", 0),
"error_count": len(performance_report.get("metrics", {}).get("slow_queries", []))
}
return metrics
except Exception as e:
logger.error(f"Metrics collection failed: {e}")
return {
"timestamp": datetime.utcnow().isoformat(),
"error": "Metrics collection failed"
}