diff --git a/airflow/api_fastapi/execution_api/app.py b/airflow/api_fastapi/execution_api/app.py index a9bbf4dd7888c..b6b36e08c1137 100644 --- a/airflow/api_fastapi/execution_api/app.py +++ b/airflow/api_fastapi/execution_api/app.py @@ -22,12 +22,17 @@ from typing import TYPE_CHECKING import attrs -from fastapi import FastAPI +from fastapi import FastAPI, Request from fastapi.openapi.utils import get_openapi +from fastapi.responses import JSONResponse if TYPE_CHECKING: import httpx +import structlog + +logger = structlog.get_logger(logger_name=__name__) + @asynccontextmanager async def lifespan(app: FastAPI): @@ -86,6 +91,16 @@ def custom_openapi() -> dict: app.openapi = custom_openapi # type: ignore[method-assign] app.include_router(execution_api_router) + + # As we are mounted as a sub app, we don't get any logs for unhandled exceptions without this! + @app.exception_handler(Exception) + def handle_exceptions(request: Request, exc: Exception): + logger.exception("Handle died with an error", exc_info=(type(exc), exc, exc.__traceback__)) + content = {"message": "Internal server error"} + if "correlation-id" in request.headers: + content["correlation-id"] = request.headers["correlation-id"] + return JSONResponse(status_code=500, content=content) + return app