1010
1111from app .api import chat as chat_api
1212from app .api import conversation_analysis as analysis_api
13+ from app .api import monitoring as monitoring_api
1314from app .api import user as user_api
1415from app .db .chat import db
16+ from app .services .cache .redis_manager import redis_manager
1517from app .utils .logger import logger
18+ from app .utils .metrics import metrics_collector
1619
1720
1821@asynccontextmanager
@@ -21,10 +24,21 @@ async def lifespan(app: FastAPI):
2124 Handles startup and shutdown events for the application.
2225 """
2326 logger .info ("Starting up..." )
27+
2428 await db .create_db_and_tables ()
2529 logger .info ("Database tables created or already exist." )
30+
31+ await redis_manager .initialize ()
32+ logger .info ("Redis cache initialized." )
33+
34+ metrics_collector .initialize ()
35+ logger .info ("Metrics collector initialized." )
36+
2637 yield
38+
2739 logger .info ("Shutting down..." )
40+ await redis_manager .close ()
41+ logger .info ("Redis connections closed." )
2842
2943
3044app = FastAPI (
@@ -142,12 +156,106 @@ async def general_exception_handler(request: Request, exc: Exception):
142156
143157@app .get ("/health" )
144158async def health_check ():
145- return {"status" : "healthy" }
159+ """Health check endpoint that validates all services."""
160+ import time
161+
162+ from .services .cache .redis_manager import redis_manager
163+ from .services .cache .semantic_cache import semantic_cache
164+ from .utils .config import app_settings
165+
166+ health_status = {
167+ "status" : "healthy" ,
168+ "timestamp" : int (time .time ()),
169+ "version" : app_settings .VERSION if hasattr (app_settings , "VERSION" ) else "unknown" ,
170+ "services" : {},
171+ }
172+
173+ try :
174+ redis_healthy = redis_manager .is_healthy
175+ health_status ["services" ]["redis" ] = {"status" : "healthy" if redis_healthy else "unhealthy" }
176+ if not redis_healthy :
177+ health_status ["status" ] = "unhealthy"
178+ except Exception as e :
179+ health_status ["services" ]["redis" ] = {"status" : "unhealthy" , "error" : str (e )}
180+ health_status ["status" ] = "unhealthy"
181+
182+ try :
183+ cache_healthy = await semantic_cache .health_check ()
184+ health_status ["services" ]["cache" ] = {"status" : "healthy" if cache_healthy else "unhealthy" }
185+ if not cache_healthy :
186+ health_status ["status" ] = "unhealthy"
187+ health_status ["services" ]["cache" ]["error" ] = "Cache health check failed"
188+ except Exception as e :
189+ health_status ["services" ]["cache" ] = {"status" : "unhealthy" , "error" : str (e )}
190+ health_status ["status" ] = "unhealthy"
191+
192+ if health_status ["status" ] == "unhealthy" :
193+ return JSONResponse (status_code = 503 , content = health_status )
194+
195+ return health_status
196+
197+
198+ @app .get ("/health/detailed" )
199+ async def health_check_detailed ():
200+ """Detailed health check with additional service information."""
201+
202+ from .services .cache .redis_manager import redis_manager
203+ from .services .cache .semantic_cache import semantic_cache
204+
205+ health_status = await health_check ()
206+ if isinstance (health_status , JSONResponse ):
207+ health_status = health_status .body .decode ()
208+ import json
209+
210+ health_status = json .loads (health_status )
211+
212+ try :
213+ if hasattr (redis_manager , "get_connection_info" ):
214+ health_status ["services" ]["redis" ]["connection_info" ] = redis_manager .get_connection_info ()
215+ except Exception :
216+ pass
217+
218+ try :
219+ if hasattr (semantic_cache , "get_stats" ):
220+ health_status ["services" ]["cache" ]["stats" ] = await semantic_cache .get_stats ()
221+ except Exception :
222+ pass
223+
224+ return health_status
225+
226+
227+ @app .get ("/metrics" )
228+ async def get_metrics ():
229+ """Prometheus metrics endpoint."""
230+ from fastapi import Response
231+
232+ from .utils .metrics import metrics_collector
233+
234+ try :
235+ metrics_data = metrics_collector .get_metrics ()
236+ return Response (content = metrics_data , media_type = "text/plain; version=0.0.4" )
237+ except Exception as e :
238+ logger .error (f"Failed to get metrics: { e } " )
239+ return Response (content = f"# Error: { str (e )} " , media_type = "text/plain; version=0.0.4" , status_code = 500 )
240+
241+
242+ @app .get ("/metrics/json" )
243+ async def get_metrics_json ():
244+ """JSON metrics endpoint."""
245+ from .utils .metrics import metrics_collector
246+
247+ try :
248+ metrics_dict = metrics_collector .get_metrics_dict ()
249+ return metrics_dict
250+ except Exception as e :
251+ logger .error (f"Failed to get metrics: { e } " )
252+ return JSONResponse (status_code = 500 , content = {"error" : str (e )})
146253
147254
148255app .include_router (user_api .router )
149256app .include_router (chat_api .router )
150257app .include_router (analysis_api .router )
258+ app .include_router (monitoring_api .router )
151259
152260
153261def run_uvicorn ():
0 commit comments