import logging from contextlib import asynccontextmanager from typing import AsyncIterator from fastapi import FastAPI, HTTPException, Request from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from app.api import router from app.checker import EndpointChecker from app.settings import Settings, get_settings from app.store import MonitorStore def configure_logging(level: str) -> None: logging.basicConfig(level=level.upper(), format="%(message)s") def create_app(settings: Settings | None = None) -> FastAPI: config = settings or get_settings() @asynccontextmanager async def lifespan(application: FastAPI) -> AsyncIterator[None]: configure_logging(config.log_level) application.state.store = MonitorStore() application.state.checker = EndpointChecker(config) yield application = FastAPI(title="Endpoint Monitor", version="1.0.0", lifespan=lifespan) application.include_router(router) @application.exception_handler(HTTPException) async def http_error(_request: Request, exc: HTTPException) -> JSONResponse: if isinstance(exc.detail, tuple): code, message = exc.detail else: code, message = "http_error", str(exc.detail) return JSONResponse(status_code=exc.status_code, content={"error": {"code": code, "message": message}}, headers=exc.headers) @application.exception_handler(RequestValidationError) async def validation_error(_request: Request, _exc: RequestValidationError) -> JSONResponse: return JSONResponse(status_code=422, content={"error": { "code": "validation_error", "message": "Request validation failed"}}) return application app = create_app()