import time from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from app.routers import apm, readiness, supply_chain, upload, dashboard from app.routers.activity import router as activity_router from app.database import init_db, log_activity # ── Init DB on startup ────────────────────────────────────────────── init_db() app = FastAPI( title="EVolve Intelligence", description="AI platform for industrial EV asset performance and supply chain intelligence.", version="1.0.0" ) import os ALLOWED_ORIGINS = os.environ.get("ALLOWED_ORIGINS", "*").split(",") app.add_middleware( CORSMiddleware, allow_origins=ALLOWED_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ── Request-level activity logging middleware ─────────────────────── # Logs every API call (except static/docs endpoints) to the DB SKIP_LOG_PREFIXES = ("/docs", "/openapi", "/redoc", "/favicon") @app.middleware("http") async def activity_logging_middleware(request: Request, call_next): path = request.url.path method = request.method # Skip noisy internal endpoints if any(path.startswith(p) for p in SKIP_LOG_PREFIXES): return await call_next(request) start = time.time() response = await call_next(request) duration_ms = round((time.time() - start) * 1000) # Only log meaningful read/write calls, not health checks if path not in ("/", "/health"): action = f"{method} {path} — {response.status_code} ({duration_ms}ms)" log_activity( action=action, endpoint=path, method=method, status_code=response.status_code, details={"duration_ms": duration_ms} ) return response # ── Routers ───────────────────────────────────────────────────────── app.include_router(apm.router) app.include_router(readiness.router) app.include_router(supply_chain.router) app.include_router(upload.router) app.include_router(dashboard.router) app.include_router(activity_router) @app.get("/") def root(): return { "service": "EVolve Intelligence", "modules": ["APM", "Fleet Readiness", "Supply Chain Risk"], "docs": "/docs" } @app.get("/health") def health(): return {"status": "ok"}