From 0b55647941c35a44d82ab30ebeddbd9217d7c59b Mon Sep 17 00:00:00 2001 From: busya Date: Wed, 27 May 2026 09:46:14 +0300 Subject: [PATCH] fix: add global exception handler to log 500 errors - Added @app.exception_handler(Exception) that logs full traceback via logger.exception() into superset_tools_app logger (visible in docker logs) - Previously FastAPI/Starlette wrote unhandled exceptions to uvicorn.error logger, making 500 errors invisible in docker logs - Added JSONResponse import for the handler --- backend/src/app.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/backend/src/app.py b/backend/src/app.py index ccdb0cf9..e15535a1 100755 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -21,7 +21,7 @@ project_root = Path(__file__).resolve().parent.parent.parent from alembic.config import Config as AlembicConfig from fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import FileResponse +from fastapi.responses import FileResponse, JSONResponse from fastapi.staticfiles import StaticFiles from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.sessions import SessionMiddleware @@ -237,6 +237,26 @@ class HSTSMiddleware(BaseHTTPMiddleware): app.add_middleware(HSTSMiddleware) # #endregion app_middleware +# #region global_exception_handler [C:2] [TYPE Function] +# @BRIEF Global exception handler — logs all unhandled 500 errors into the app logger. +# @PRE request is a FastAPI Request object. +# @POST Logs full traceback to superset_tools_app logger; returns 500. +# @RATIONALE FastAPI/Starlette writes unhandled exceptions to uvicorn.error logger, +# which is not captured in docker logs. This handler ensures every 500 +# appears in our structured JSON log output. +@app.exception_handler(Exception) +async def global_exception_handler(request: Request, exc: Exception): + logger.exception( + f"Unhandled exception: {request.method} {request.url.path}", + extra={"src": "app.exception_handler", "path": request.url.path, "method": request.method}, + ) + return JSONResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content={"detail": "Internal server error", "path": request.url.path}, + ) +# #endregion global_exception_handler + + # #region network_error_handler [C:1] [TYPE Function] # @BRIEF Global exception handler for NetworkError. # @PRE request is a FastAPI Request object.