From 37c2ac3717845eda130aa04f5881b841096f68d3 Mon Sep 17 00:00:00 2001 From: Markov Date: Sun, 15 Feb 2026 19:36:49 +0100 Subject: [PATCH] feat: request/response logging, CORS, error handling --- src/tracker/app.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/tracker/app.py b/src/tracker/app.py index c1e89e7..742f434 100644 --- a/src/tracker/app.py +++ b/src/tracker/app.py @@ -1,8 +1,12 @@ """FastAPI application.""" import logging +import time +import traceback -from fastapi import FastAPI +from fastapi import FastAPI, Request +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse from tracker.api import agents, labels, projects, tasks from tracker.config import settings @@ -12,6 +16,7 @@ logging.basicConfig( level=logging.DEBUG if settings.env == "dev" else logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s", ) +logger = logging.getLogger("tracker") app = FastAPI( title="Team Board Tracker", @@ -19,6 +24,38 @@ app = FastAPI( docs_url="/docs" if settings.env == "dev" else None, ) + +@app.middleware("http") +async def log_requests(request: Request, call_next): + start = time.time() + body = None + if request.method in ("POST", "PUT", "PATCH"): + try: + body = await request.body() + logger.info("[REQ] %s %s body=%s", request.method, request.url.path, body.decode()[:500]) + except Exception: + pass + else: + logger.info("[REQ] %s %s", request.method, request.url.path) + + try: + response = await call_next(request) + elapsed = (time.time() - start) * 1000 + logger.info("[RES] %s %s → %d (%.0fms)", request.method, request.url.path, response.status_code, elapsed) + return response + except Exception as e: + elapsed = (time.time() - start) * 1000 + logger.error("[ERR] %s %s → %s (%.0fms)\n%s", request.method, request.url.path, str(e), elapsed, traceback.format_exc()) + return JSONResponse({"error": str(e)}, status_code=500) + +# CORS +app.add_middleware( + CORSMiddleware, + allow_origins=["https://team.uix.su", "http://localhost:3100"], + allow_methods=["*"], + allow_headers=["*"], +) + # REST API app.include_router(projects.router, prefix="/api/v1") app.include_router(tasks.router, prefix="/api/v1")