BrejBala's picture
Deploy backend Docker app
e63c592
import logging
from typing import Any
from fastapi import FastAPI, HTTPException, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from starlette import status
logger = logging.getLogger(__name__)
class PineconeIndexConfigError(RuntimeError):
"""Raised when the Pinecone index is not configured for integrated embeddings."""
class UpstreamServiceError(RuntimeError):
"""Raised when an upstream dependency (LLM, web search, etc.) fails."""
def __init__(self, service: str, message: str) -> None:
self.service = service
super().__init__(message)
def setup_exception_handlers(app: FastAPI) -> None:
"""Register global exception handlers on the FastAPI app."""
@app.exception_handler(PineconeIndexConfigError)
async def pinecone_index_config_error_handler(
request: Request, exc: PineconeIndexConfigError
) -> JSONResponse:
logger.error("Pinecone index configuration error: %s", exc)
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content={"detail": str(exc)},
)
@app.exception_handler(UpstreamServiceError)
async def upstream_service_error_handler(
request: Request, exc: UpstreamServiceError
) -> JSONResponse:
logger.error("Upstream service error from %s: %s", exc.service, exc)
return JSONResponse(
status_code=status.HTTP_502_BAD_GATEWAY,
content={"detail": str(exc)},
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request, exc: RequestValidationError
) -> JSONResponse:
logger.warning("Request validation error: %s", exc)
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": exc.errors()},
)
@app.exception_handler(HTTPException)
async def http_exception_handler(
request: Request, exc: HTTPException
) -> JSONResponse:
# Let FastAPI-style HTTPException pass through with its status and detail.
logger.warning(
"HTTPException raised: status=%s detail=%s",
exc.status_code,
exc.detail,
)
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)
@app.exception_handler(Exception)
async def generic_exception_handler(
request: Request, exc: Exception
) -> JSONResponse:
logger.exception("Unhandled error", exc_info=exc)
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content={"detail": "Internal server error"},
)
__all__ = ["PineconeIndexConfigError", "setup_exception_handlers"]