import traceback import os from pathlib import Path from fastapi import FastAPI, Request, HTTPException, Response from fastapi.templating import Jinja2Templates from fastapi.responses import HTMLResponse from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST import time import logging import markdown from routes import router as routes_app logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI(title="DevOps Windows API", description="Application de démonstration DevOps sous Windows", version="1.0.0") # 🔹 Utilise un chemin absolu pour le dossier templates BASE_DIR = Path(__file__).resolve().parent templates = Jinja2Templates(directory=str(BASE_DIR / "templates")) app.include_router(routes_app, prefix="/users", tags=["users"]) REQUEST_COUNT = Counter('http_requests_total', 'Total des requêtes HTTP', ['method', 'endpoint', 'status']) REQUEST_LATENCY = Histogram('http_request_duration_seconds', 'Temps de réponse HTTP', ['method', 'endpoint']) @app.middleware("http") async def monitor_requests(request: Request, call_next): start_time = time.time() try: response = await call_next(request) status_code = str(response.status_code) except Exception as e: status_code = "500" response = Response(content=f"Erreur serveur : {str(e)}", status_code=500) process_time = time.time() - start_time REQUEST_COUNT.labels(method=request.method, endpoint=request.url.path, status=status_code).inc() REQUEST_LATENCY.labels(method=request.method, endpoint=request.url.path).observe(process_time) response.headers["X-Process-Time"] = f"{process_time:.3f}s" return response @app.get("/", response_class=HTMLResponse) async def home(request: Request): md_file_path = "/app/readme.md" try: with open(md_file_path, "r", encoding="utf-8") as f: md_content = f.read() html_content = markdown.markdown(md_content) except Exception as e: html_content = f"
{traceback.format_exc()}"
header_banner = "🚀 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ DevOps Stack Windows - Fonctionnel ! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
try:
return templates.TemplateResponse("index.html", {
"request": request,
"header": header_banner,
"content": html_content
})
except Exception as e:
return HTMLResponse(f"{traceback.format_exc()}", status_code=500)
@app.get("/health")
async def health(): return {"status": "healthy", "timestamp": time.time(), "service": "devops-app"}
@app.get("/metrics")
async def metrics():
try: return Response(content=generate_latest(), media_type=CONTENT_TYPE_LATEST)
except Exception as e: raise HTTPException(status_code=500, detail="Échec des métriques")
@app.get("/info")
async def info(): return {
"python_version": "3.11", "platform": "windows", "service": "FastAPI DevOps",
"features": ["docker", "kubernetes", "monitoring", "ci-cd"]
}
@app.get("/env")
async def show_env(): return {"ENV": os.getenv("ENV", "not-set"), "HOSTNAME": os.getenv("HOSTNAME", "not-set")}