Skip to content

Instantly share code, notes, and snippets.

@jhamerski
Created February 9, 2025 01:16
Show Gist options
  • Save jhamerski/35ea2b57560334c3066380140a134ae2 to your computer and use it in GitHub Desktop.
Save jhamerski/35ea2b57560334c3066380140a134ae2 to your computer and use it in GitHub Desktop.
from fastapi import FastAPI
from app.webhook.webhook_router import router as webhook_router
from app.person.person_router import router as person_router
def configure_app(app: FastAPI):
app.include_router(webhook_router, tags=["Webhook"])
app.include_router(person_router, tags=["Person"])
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from datetime import datetime
from generics.logger import logger
import uuid
import json
class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
request_id = str(uuid.uuid4())
start_time = datetime.now()
if request.method == "GET" and request.url.path in ("/", "/redoc", "/docs", "/openapi.json", "/favicon.ico"):
return await call_next(request)
# Lê o corpo da requisição e prepara para reutilização
request_body = await request.body()
if request_body:
try:
request_body_json = request_body.decode("utf-8")
logger.info(
f"Request ID: {request_id} | Request Body: {request_body_json} | Body Size: {len(request_body)} bytes")
except json.JSONDecodeError:
logger.warning(f"Request ID: {request_id} | Failed to decode request body as JSON.")
else:
logger.info(f"Request ID: {request_id} | Request Body is empty")
logger.info(
f"Request ID: {request_id} | Method: {request.method} | URL: {request.url} | Headers: {dict(request.headers)}")
# Substituir o request para permitir a reutilização do corpo
request = Request(request.scope, receive=lambda: request_body)
try:
response: Response = await call_next(request)
except Exception as e:
process_time = (datetime.now() - start_time).total_seconds()
logger.error(
f"Request ID: {request_id} | Route: {request.url.path} | Time: {process_time} seconds | Exception: {str(e)}")
raise e
else:
process_time = (datetime.now() - start_time).total_seconds()
# Registrar o corpo da resposta
response_body = b""
async for chunk in response.body_iterator:
response_body += chunk
logger.info(f"Request ID: {request_id} | Response Body: {response_body.decode('utf-8')}")
# Criar uma nova resposta com o corpo registrado
response = Response(
content=response_body,
status_code=response.status_code,
headers=dict(response.headers),
media_type=response.media_type
)
if response.status_code >= 400:
logger.error(
f"Request ID: {request_id} | Response Status: {response.status_code} | Route: {request.url.path} | Time: {process_time} seconds") # noqa
else:
logger.info(
f"Request ID: {request_id} | Response Status: {response.status_code} | Route: {request.url.path} | Time: {process_time} seconds") # noqa
return response
from contextlib import asynccontextmanager
import uvicorn
from fastapi import FastAPI
from app.all_routers import all_routers
from core.middlewares.middleware_exception import ExceptionMiddleware
from core.settings.database import init_db, close_db
from core.settings.documentation import title, version, description
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Ciclo de vida do banco de dados"""
await init_db()
yield
await close_db()
middleware = [
Middleware(LoggingMiddleware),
Middleware(ExceptionMiddleware)
]
# Pode utilizar a dependenci aqui ao iniciar o APP
app = FastAPI(lifespan=lifespan, docs_url="/", title=title, version=version, description=description, middleware=middleware)
all_routers.configure_app(app)
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, access_log=False, log_level="debug", reload=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment