Edwin Salguero
Enterprise: Transform to production-grade architecture with FastAPI, Docker, K8s, monitoring, and comprehensive tooling
832348e
#!/usr/bin/env python3 | |
""" | |
FRED ML - Main Application Entry Point | |
Production-grade FastAPI application for economic data analysis | |
""" | |
import logging | |
import os | |
from contextlib import asynccontextmanager | |
import uvicorn | |
from fastapi import Depends, FastAPI, HTTPException | |
from fastapi.middleware.cors import CORSMiddleware | |
from fastapi.responses import JSONResponse | |
from config.settings import FRED_API_KEY | |
from src.analysis.advanced_analytics import AdvancedAnalytics | |
from src.core.fred_client import FREDDataCollectorV2 | |
# Configure logging | |
logging.basicConfig( | |
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" | |
) | |
logger = logging.getLogger(__name__) | |
# Global variables for application state | |
collector = None | |
analytics = None | |
async def lifespan(app: FastAPI): | |
"""Application lifespan manager""" | |
# Startup | |
global collector, analytics | |
logger.info("Starting FRED ML application...") | |
if not FRED_API_KEY: | |
logger.error("FRED_API_KEY not configured") | |
raise ValueError("FRED_API_KEY environment variable is required") | |
collector = FREDDataCollectorV2(api_key=FRED_API_KEY) | |
logger.info("FRED Data Collector initialized") | |
yield | |
# Shutdown | |
logger.info("Shutting down FRED ML application...") | |
# Create FastAPI application | |
app = FastAPI( | |
title="FRED ML API", | |
description="Economic Data Analysis API using Federal Reserve Economic Data", | |
version="1.0.0", | |
lifespan=lifespan, | |
) | |
# Add CORS middleware | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["*"], | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
async def root(): | |
"""Root endpoint""" | |
return {"message": "FRED ML API", "version": "1.0.0", "status": "running"} | |
async def health_check(): | |
"""Health check endpoint""" | |
return {"status": "healthy"} | |
async def readiness_check(): | |
"""Readiness check endpoint""" | |
if collector is None: | |
raise HTTPException(status_code=503, detail="Service not ready") | |
return {"status": "ready"} | |
async def get_indicators(): | |
"""Get available economic indicators""" | |
if collector is None: | |
raise HTTPException(status_code=503, detail="Service not ready") | |
return { | |
"indicators": list(collector.indicators.keys()), | |
"descriptions": collector.indicators, | |
} | |
async def analyze_data( | |
series_ids: list[str], start_date: str = None, end_date: str = None | |
): | |
"""Analyze economic data for specified series""" | |
if collector is None: | |
raise HTTPException(status_code=503, detail="Service not ready") | |
try: | |
df, summary = collector.run_analysis( | |
series_ids=series_ids, start_date=start_date, end_date=end_date | |
) | |
return { | |
"status": "success", | |
"data_shape": df.shape if df is not None else None, | |
"summary": summary.to_dict() if summary is not None else None, | |
} | |
except Exception as e: | |
logger.error(f"Analysis failed: {e}") | |
raise HTTPException(status_code=500, detail=str(e)) | |
async def get_status(): | |
"""Get application status""" | |
return { | |
"api_key_configured": bool(FRED_API_KEY), | |
"collector_initialized": collector is not None, | |
"environment": os.getenv("ENVIRONMENT", "development"), | |
} | |
if __name__ == "__main__": | |
port = int(os.getenv("PORT", 8000)) | |
uvicorn.run( | |
"src.main:app", | |
host="0.0.0.0", | |
port=port, | |
reload=os.getenv("ENVIRONMENT") == "development", | |
) | |