Maia/backend/app/main.py

93 lines
2.9 KiB
Python

import logging
import json
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
from app.routers import auth, meetings, analyses
from app.config import settings
from app.services.websocket_service import manager
class JSONFormatter(logging.Formatter):
def format(self, record):
log_record = {
"level": record.levelname,
"message": record.getMessage(),
"logger": record.name,
"time": self.formatTime(record),
}
if record.exc_info:
log_record["exception"] = self.formatException(record.exc_info)
return json.dumps(log_record, ensure_ascii=False)
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logging.basicConfig(handlers=[handler], level=logging.INFO, force=True)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info(json.dumps({"event": "startup", "message": "Meeting Assistant API starting"}))
yield
logger.info(json.dumps({"event": "shutdown", "message": "Meeting Assistant API stopping"}))
app = FastAPI(
title="Meeting Assistant API",
description="Orchestration server for Meeting Assistant - middleware between Mobile App and AI services",
version="1.0.0",
lifespan=lifespan,
docs_url="/docs",
redoc_url="/redoc",
)
origins = settings.ALLOWED_ORIGINS.split(",") if settings.ALLOWED_ORIGINS != "*" else ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
app.include_router(meetings.router, prefix="/api/meetings", tags=["meetings"])
app.include_router(analyses.router, prefix="/api", tags=["analyses"])
@app.get("/health", tags=["health"])
async def health_check():
return {
"status": "healthy",
"service": "meeting-assistant-api",
"version": "1.0.0",
}
@app.websocket("/ws/meetings/{meeting_id}")
async def websocket_endpoint(websocket: WebSocket, meeting_id: str):
await manager.connect(websocket, meeting_id)
try:
while True:
data = await websocket.receive_text()
await manager.send_message(meeting_id, {"type": "ping", "data": data})
except WebSocketDisconnect:
manager.disconnect(websocket, meeting_id)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
logger.error(json.dumps({
"event": "unhandled_exception",
"error": str(exc),
"path": str(request.url),
"method": request.method,
}))
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)