feat: Ajout monitoring Prometheus/Grafana et configuration déploiement serveur Linux

- Ajout Prometheus et Grafana au docker-compose.yml
- Métriques automatiques pour le backend FastAPI
- Configuration de production avec docker-compose.prod.yml
- Guide de déploiement manuel pour serveur Linux
- Variables d'environnement sécurisées
- Documentation complète de déploiement
This commit is contained in:
Rassaby Ludovic
2025-10-16 11:29:16 +04:00
parent 091e2d320f
commit b8d075a2bd
15 changed files with 885 additions and 54 deletions
+43 -1
View File
@@ -1,10 +1,12 @@
from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import asyncpg
from datetime import datetime, date, time
import os
import time as time_module
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
# Configuration de la base de données
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@db:5432/dockezr")
@@ -12,6 +14,12 @@ DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@db:5432/doc
# Pool de connexions
pool = None
# Métriques Prometheus
REQUEST_COUNT = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint', 'status'])
REQUEST_DURATION = Histogram('http_request_duration_seconds', 'HTTP request duration', ['method', 'endpoint'])
RESERVATION_COUNT = Counter('reservations_total', 'Total reservations created', ['room_name'])
ROOM_ACCESS_COUNT = Counter('room_access_total', 'Total room accesses', ['room_name'])
# Modèles Pydantic pour les Salles
class RoomCreate(BaseModel):
name: str
@@ -64,6 +72,27 @@ app.add_middleware(
allow_headers=["*"],
)
# Middleware pour les métriques Prometheus
@app.middleware("http")
async def prometheus_middleware(request: Request, call_next):
start_time = time_module.time()
# Extraire les informations de la requête
method = request.method
endpoint = request.url.path
# Traiter la requête
response = await call_next(request)
# Calculer la durée
duration = time_module.time() - start_time
# Enregistrer les métriques
REQUEST_COUNT.labels(method=method, endpoint=endpoint, status=response.status_code).inc()
REQUEST_DURATION.labels(method=method, endpoint=endpoint).observe(duration)
return response
@app.on_event("startup")
async def startup():
global pool
@@ -120,6 +149,11 @@ async def root():
async def health_check():
return {"status": "healthy", "database": "connected"}
@app.get("/metrics")
async def metrics():
"""Endpoint pour les métriques Prometheus"""
return Response(generate_latest(), media_type=CONTENT_TYPE_LATEST)
# === ROUTES POUR LES SALLES ===
@app.get("/rooms", response_model=List[Room])
@@ -136,6 +170,10 @@ async def get_room(room_id: int):
row = await conn.fetchrow('SELECT * FROM rooms WHERE id = $1', room_id)
if row is None:
raise HTTPException(status_code=404, detail="Salle non trouvée")
# Enregistrer l'accès à la salle
ROOM_ACCESS_COUNT.labels(room_name=row['name']).inc()
return dict(row)
@app.post("/rooms", response_model=Room)
@@ -243,6 +281,10 @@ async def create_reservation(reservation: ReservationCreate):
result = dict(row)
result['room_name'] = room['name']
# Enregistrer la création de réservation
RESERVATION_COUNT.labels(room_name=room['name']).inc()
return result
@app.delete("/reservations/{reservation_id}")