Coverage for src/alprina_cli/api/routes/health_check.py: 0%
37 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
1"""
2Health check and diagnostics endpoints.
3"""
5from fastapi import APIRouter
6from typing import Dict, Any
7from loguru import logger
9from ..services.neon_service import neon_service
11router = APIRouter()
14@app.get("/v1/health/detailed")
15async def detailed_health_check() -> Dict[str, Any]:
16 """
17 Detailed health check with database connection status.
18 """
19 health = {
20 "api": "healthy",
21 "database": {
22 "enabled": False,
23 "connected": False,
24 "pool_initialized": False,
25 "error": None
26 }
27 }
29 # Check Neon service
30 if neon_service.is_enabled():
31 health["database"]["enabled"] = True
33 try:
34 pool = await neon_service.get_pool()
35 health["database"]["pool_initialized"] = True
37 # Test query
38 async with pool.acquire() as conn:
39 version = await conn.fetchval("SELECT version()")
40 health["database"]["connected"] = True
41 health["database"]["version"] = version[:50] # First 50 chars
43 # Count tables
44 table_count = await conn.fetchval(
45 """
46 SELECT COUNT(*) FROM information_schema.tables
47 WHERE table_schema = 'public'
48 """
49 )
50 health["database"]["tables_count"] = table_count
52 # Count rows in key tables
53 health["database"]["row_counts"] = {
54 "users": await conn.fetchval("SELECT COUNT(*) FROM users"),
55 "webhook_events": await conn.fetchval("SELECT COUNT(*) FROM webhook_events"),
56 "api_keys": await conn.fetchval("SELECT COUNT(*) FROM api_keys"),
57 "scans": await conn.fetchval("SELECT COUNT(*) FROM scans")
58 }
60 except Exception as e:
61 health["database"]["error"] = str(e)
62 logger.error(f"Health check database error: {e}")
64 return health
67@app.get("/v1/health/database-test")
68async def database_test() -> Dict[str, Any]:
69 """
70 Test database write capability.
71 """
72 if not neon_service.is_enabled():
73 return {"error": "Database not enabled"}
75 try:
76 pool = await neon_service.get_pool()
78 async with pool.acquire() as conn:
79 # Try to insert a test webhook event
80 await conn.execute(
81 """
82 INSERT INTO webhook_events (event_type, event_id, payload)
83 VALUES ($1, $2, $3)
84 ON CONFLICT (event_id) DO NOTHING
85 """,
86 "test.health_check",
87 f"test_health_{datetime.utcnow().timestamp()}",
88 {"test": True}
89 )
91 # Count webhooks
92 count = await conn.fetchval("SELECT COUNT(*) FROM webhook_events")
94 return {
95 "status": "success",
96 "message": "Database write test passed",
97 "webhook_events_count": count
98 }
100 except Exception as e:
101 logger.error(f"Database test failed: {e}")
102 return {
103 "status": "error",
104 "message": str(e)
105 }