import os os.environ["NUMEXPR_MAX_THREADS"] = "12" from fastapi import FastAPI, HTTPException, Depends, Body, status, Response from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager import logging from logging.handlers import RotatingFileHandler from datetime import timedelta import pathlib from modules.shared.configuration import APP_CONFIG def initLogging(): # Get log level from config (default to INFO if not found) logLevelName = APP_CONFIG.get("APP_LOGGING_LOG_LEVEL", "WARNING") logLevel = getattr(logging, logLevelName) # Configure handlers based on config handlers = [] # Add console handler if enabled if APP_CONFIG.get("APP_LOGGING_CONSOLE_ENABLED", True): consoleHandler = logging.StreamHandler() handlers.append(consoleHandler) # Add file handler if enabled if APP_CONFIG.get("APP_LOGGING_FILE_ENABLED", True): logFile = APP_CONFIG.get("APP_LOGGING_LOG_FILE", "app.log") rotationSize = int(APP_CONFIG.get("APP_LOGGING_ROTATION_SIZE", 10485760)) # Default: 10MB backupCount = int(APP_CONFIG.get("APP_LOGGING_BACKUP_COUNT", 5)) fileHandler = RotatingFileHandler( logFile, maxBytes=rotationSize, backupCount=backupCount ) handlers.append(fileHandler) # Configure the logger logging.basicConfig( level=logLevel, format=APP_CONFIG.get("APP_LOGGING_FORMAT", "%(asctime)s - %(levelname)s - %(name)s - %(message)s"), datefmt=APP_CONFIG.get("APP_LOGGING_DATE_FORMAT", "%Y-%m-%d %H:%M:%S"), handlers=handlers ) # Silence noisy third-party libraries - use the same level as the root logger noisyLoggers = ["httpx", "urllib3", "asyncio", "fastapi.security.oauth2"] for loggerName in noisyLoggers: logging.getLogger(loggerName).setLevel(logLevel) # Initialize logging initLogging() logger = logging.getLogger(__name__) instanceLabel = APP_CONFIG.get("APP_ENV_LABEL") # Define lifespan context manager for application startup/shutdown events @asynccontextmanager async def lifespan(app: FastAPI): # Startup logic logger.info("Application is starting up") yield # Shutdown logic logger.info("Application has been shut down") # START APP app = FastAPI( title="PowerOn | Data Platform API", description=f"Backend API for the Multi-Agent Platform by ValueOn AG ({instanceLabel})", lifespan=lifespan ) # Parse CORS origins from environment variable def get_allowed_origins(): origins_str = APP_CONFIG.get("APP_ALLOWED_ORIGINS", "http://localhost:8080") # Split by comma and strip whitespace origins = [origin.strip() for origin in origins_str.split(",")] logger.info(f"CORS allowed origins: {origins}") return origins # CORS configuration using environment variables app.add_middleware( CORSMiddleware, allow_origins= get_allowed_origins(), allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["*"], expose_headers=["*"], max_age=86400 # Increased caching for preflight requests ) # Include all routers from modules.routes.routeGeneral import router as generalRouter app.include_router(generalRouter) from modules.routes.routeAttributes import router as attributesRouter app.include_router(attributesRouter) from modules.routes.routeMandates import router as mandateRouter app.include_router(mandateRouter) from modules.routes.routeUsers import router as userRouter app.include_router(userRouter) from modules.routes.routeFiles import router as fileRouter app.include_router(fileRouter) from modules.routes.routePrompts import router as promptRouter app.include_router(promptRouter) from modules.routes.routeWorkflows import router as workflowRouter app.include_router(workflowRouter) from modules.routes.routeMsft import router as msftRouter app.include_router(msftRouter) from modules.routes.routeGoogle import router as googleRouter app.include_router(googleRouter)