From b73be057f3b266e5cf9cc545f9680a36732559f3 Mon Sep 17 00:00:00 2001 From: Edwin Eames Date: Fri, 27 Feb 2026 18:40:52 -0500 Subject: [PATCH] feat: standardize main.py with health checks, structured logging, and API docs - Add module-level docstring with endpoint documentation - Add /health endpoint with database connectivity check - Add root endpoint redirecting to API docs - Add FastAPI metadata (title, description, version) - Reorganize imports and code structure with section separators - Add shutdown event handler - Change failed DB connection log level to warning --- main.py | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index 7ea49e1..5089bb3 100644 --- a/main.py +++ b/main.py @@ -1,19 +1,48 @@ +""" +eamco_money_api - FastAPI Delivery Pricing Microservice. + +This microservice provides endpoints for managing delivery pricing, +cost calculations, and financial data for oil deliveries. + +Endpoints: + GET /health - Health check with database connectivity status + GET /delivery/... - Delivery pricing and cost endpoints + +Usage: + # Development + uvicorn main:app --reload --host 0.0.0.0 --port 8000 + + # Production (Docker) + docker run -p 8000:8000 eamco_money_api +""" + import logging import sys import uuid + from fastapi import FastAPI, Request -from app.routers import delivery from fastapi.middleware.cors import CORSMiddleware from starlette.middleware.base import BaseHTTPMiddleware -from config import load_config from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker +from config import load_config +from app.routers import delivery + + +# ============================================================================= +# CONFIGURATION +# ============================================================================= ApplicationConfig = load_config() -# Configure logging - DEBUG in development, INFO in production +# ============================================================================= +# LOGGING CONFIGURATION +# ============================================================================= + + def setup_logging(): + """Configure structured logging for the application.""" log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO formatter = logging.Formatter( @@ -34,9 +63,13 @@ def setup_logging(): return logging.getLogger('eamco_money_api') + logger = setup_logging() -# Database setup with connection pooling +# ============================================================================= +# DATABASE SETUP +# ============================================================================= + engine = create_engine( ApplicationConfig.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True, @@ -46,6 +79,7 @@ engine = create_engine( ) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + def check_db_connection(): """ Test database connectivity. @@ -58,11 +92,27 @@ def check_db_connection(): except Exception: return False -app = FastAPI() + +# ============================================================================= +# FASTAPI APPLICATION +# ============================================================================= + +app = FastAPI( + title="eamco_money_api", + description="Delivery pricing and cost calculation microservice", + version="1.0.0", + docs_url="/docs", + redoc_url="/redoc", +) + +# ============================================================================= +# MIDDLEWARE +# ============================================================================= -# Request ID middleware for request tracking/correlation class RequestIDMiddleware(BaseHTTPMiddleware): + """Request ID middleware for request tracking/correlation.""" + async def dispatch(self, request: Request, call_next): request_id = request.headers.get("X-Request-ID") or str(uuid.uuid4())[:8] request.state.request_id = request_id @@ -70,11 +120,9 @@ class RequestIDMiddleware(BaseHTTPMiddleware): response.headers["X-Request-ID"] = request_id return response + app.add_middleware(RequestIDMiddleware) -app.include_router(delivery.router) - - app.add_middleware( CORSMiddleware, allow_origins=ApplicationConfig.origins, @@ -83,9 +131,50 @@ app.add_middleware( allow_headers=["*"], ) -@app.get("/") -def read_root(): - return {"Status": "Money Service is online"} +# ============================================================================= +# ROUTERS +# ============================================================================= + +app.include_router(delivery.router) + +# ============================================================================= +# ENDPOINTS +# ============================================================================= + + +@app.get("/", include_in_schema=False) +async def root(): + """Root endpoint - redirect to docs.""" + return { + "service": "eamco_money_api", + "version": "1.0.0", + "docs": "/docs", + } + + +@app.get("/health", tags=["Health"]) +async def health_check(): + """ + Health check endpoint. + + Returns service status and database connectivity. + Use this endpoint for container health checks and monitoring. + + Returns: + JSON with status and db_connected flag + """ + db_connected = check_db_connection() + + return { + "status": "healthy" if db_connected else "degraded", + "db_connected": db_connected, + } + + +# ============================================================================= +# STARTUP/SHUTDOWN EVENTS +# ============================================================================= + @app.on_event("startup") async def startup_event(): @@ -107,4 +196,10 @@ async def startup_event(): if check_db_connection(): logger.info("DB Connection: ✅ OK") else: - logger.info("DB Connection: ❌ FAILED") + logger.warning("DB Connection: ❌ FAILED") + + +@app.on_event("shutdown") +async def shutdown_event(): + """Application shutdown - cleanup.""" + logger.info("🛑 eamco_money_api SHUTTING DOWN")