# PR5 — Timeouts & Observabilité (handlers + stack traces + readyz) ## Résumé Cette PR corrige les problèmes **MOD-P1-004**, **MOD-P1-005**, et **MOD-P1-006** : - **MOD-P1-004**: Timeouts context systématiques dans handlers - **MOD-P1-005**: Stack traces conditionnels (dev/DEBUG seulement) - **MOD-P1-006**: /readyz tolérance Redis/RabbitMQ (degraded mode) ## Items Corrigés ### MOD-P1-004: Pas de Timeout Context dans Tous Handlers **Fichiers**: - `internal/api/router.go:83` (déjà implémenté) - `internal/middleware/timeout.go` (déjà implémenté) **Problème**: - Handlers peuvent bloquer indéfiniment sans timeout **Fix**: - ✅ **Déjà implémenté**: Le router utilise `middleware.Timeout(r.config.HandlerTimeout)` globalement - ✅ **Validation**: Tous les handlers passent par le middleware timeout (30s par défaut) **Validation**: ```bash # Vérifier que le middleware timeout est appliqué grep -n "middleware.Timeout" internal/api/router.go # → ligne 83: router.Use(middleware.Timeout(r.config.HandlerTimeout)) ``` ### MOD-P1-005: Stack Traces dans Logs Prod **Fichiers**: - `internal/api/router.go:62-64` (modifié) - `internal/middleware/error_handler.go:148-151` (déjà implémenté) **Problème**: - Stack traces toujours loggés même en production (peut exposer info sensible) **Fix**: 1. **Amélioration de la logique**: Modifié `includeStackTrace` pour vérifier `APP_ENV=development` OU `LOG_LEVEL=DEBUG` - Avant: `includeStackTrace := r.config.Env != config.EnvProduction` (incluait staging) - Après: `includeStackTrace := r.config.Env == config.EnvDevelopment || r.config.LogLevel == "DEBUG"` 2. **Error Handler**: Déjà implémenté avec condition `if includeStackTrace` **Validation**: ```bash # Test existant go test ./internal/middleware -v -count=1 -run TestErrorHandler_StackTrace # ✅ PASS (2 tests: avec et sans stack trace) ``` ### MOD-P1-006: /readyz Échoue si Redis/RabbitMQ Down **Fichiers**: - `internal/handlers/health.go:142-184` (déjà implémenté) **Problème**: - `/readyz` peut échouer si Redis/RabbitMQ down (même si DB OK) **Fix**: - ✅ **Déjà implémenté**: `/readyz` retourne status "degraded" si Redis/RabbitMQ down, mais reste 200 OK - ✅ **DB critique**: Si DB down → 503 "not_ready" - ✅ **Services optionnels**: Si Redis/RabbitMQ down → 200 "degraded" **Validation**: ```bash # Tests ajoutés go test ./internal/handlers -v -count=1 -run TestHealthHandler_Readiness # ✅ PASS (2 tests: degraded mode et database critical) ``` ## Fichiers Modifiés 1. `internal/api/router.go` - Ligne 62-64: Amélioration de la logique `includeStackTrace` pour MOD-P1-005 - Commentaire MOD-P1-005 ajouté 2. `internal/handlers/health_p1_test.go` (nouveau) - Test `TestHealthHandler_Readiness_DegradedMode`: Valide que /readyz retourne "degraded" si Redis/RabbitMQ down - Test `TestHealthHandler_Readiness_DatabaseCritical`: Valide que /readyz retourne "not_ready" si DB down ## Commandes de Validation ### Build ```bash # Compilation go build ./internal/api ./internal/middleware ./internal/handlers # ✅ Succès # Build complet go build ./cmd/api/main.go # ✅ Succès ``` ### Tests ```bash # Tests stack traces (MOD-P1-005) go test ./internal/middleware -v -count=1 -run TestErrorHandler_StackTrace # ✅ PASS (2 tests: IncludeStackTrace_True, IncludeStackTrace_False) # Tests health readiness (MOD-P1-006) go test ./internal/handlers -v -count=1 -run TestHealthHandler_Readiness # ✅ PASS (2 tests: DegradedMode, DatabaseCritical) # Tous les tests go test ./... -count=1 -short # ✅ Tests unitaires passent ``` ### Validation Manuelle **MOD-P1-004 (Timeouts)**: - ✅ Middleware timeout appliqué globalement dans `router.go:83` - ✅ Timeout par défaut: 30s (configurable via `HANDLER_TIMEOUT`) - ✅ Tous les handlers passent par le middleware timeout **MOD-P1-005 (Stack Traces)**: ```bash # En production (APP_ENV=production, LOG_LEVEL=INFO) # → Stack traces NE sont PAS loggés ✅ # En development (APP_ENV=development) # → Stack traces SONT loggés ✅ # En DEBUG (LOG_LEVEL=DEBUG) # → Stack traces SONT loggés ✅ ``` **MOD-P1-006 (Health Readiness)**: ```bash # DB OK, Redis/RabbitMQ down curl http://localhost:8080/api/v1/readyz # → Status: 200 OK, body: {"status": "degraded", ...} ✅ # DB down # → Status: 503 Service Unavailable, body: {"status": "not_ready", ...} ✅ ``` ## Détails Techniques ### Corrections Apportées 1. **MOD-P1-004 (Timeouts)**: - ✅ **Déjà implémenté**: Middleware timeout global dans `router.go:83` - ✅ **Timeout par défaut**: 30s (configurable via `HANDLER_TIMEOUT`) - ✅ **Comportement**: Handlers timeout après 30s, retourne 504 Gateway Timeout 2. **MOD-P1-005 (Stack Traces)**: - **Avant**: `includeStackTrace := r.config.Env != config.EnvProduction` (incluait staging) - **Après**: `includeStackTrace := r.config.Env == config.EnvDevelopment || r.config.LogLevel == "DEBUG"` - **Comportement**: Stack traces seulement en development ou si LOG_LEVEL=DEBUG 3. **MOD-P1-006 (Health Readiness)**: - ✅ **Déjà implémenté**: `/readyz` retourne "degraded" si Redis/RabbitMQ down - ✅ **DB critique**: Si DB down → 503 "not_ready" - ✅ **Services optionnels**: Si Redis/RabbitMQ down → 200 "degraded" ### Endpoints Vérifiés - ✅ **Tous les handlers**: Passent par `middleware.Timeout()` global - ✅ `/api/v1/readyz`: Retourne "degraded" si Redis/RabbitMQ down, "not_ready" si DB down - ✅ **Error Handler**: Stack traces conditionnels selon env/LOG_LEVEL ## Risques / Limitations 1. **Timeouts globaux**: Le middleware timeout est appliqué globalement - **Impact**: Tous les handlers ont le même timeout (30s) - **Mitigation**: Timeout configurable via `HANDLER_TIMEOUT` env var 2. **Stack traces en staging**: Stack traces ne sont plus loggés en staging (seulement dev/DEBUG) - **Impact**: Debugging plus difficile en staging - **Mitigation**: Utiliser Sentry pour les erreurs en staging/prod 3. **Health checks**: Tests utilisent SQLite en mémoire - **Impact**: Tests ne reflètent pas exactement le comportement avec PostgreSQL - **Mitigation**: Tests d'intégration avec PostgreSQL pourraient valider le comportement réel ## Tests Ajoutés/Modifiés - ✅ `TestErrorHandler_StackTrace` (existant): Valide stack traces conditionnels - ✅ `TestHealthHandler_Readiness_DegradedMode` (nouveau): Valide degraded mode - ✅ `TestHealthHandler_Readiness_DatabaseCritical` (nouveau): Valide DB critique ## Documentation **Comportement attendu**: - **Timeouts**: Tous les handlers timeout après 30s (configurable) - **Stack traces**: Loggés seulement si `APP_ENV=development` OU `LOG_LEVEL=DEBUG` - **Health readiness**: - DB down → 503 "not_ready" - Redis/RabbitMQ down → 200 "degraded" - Tout OK → 200 "ready" **Configuration**: - `HANDLER_TIMEOUT`: Timeout pour handlers (défaut: 30s) - `APP_ENV`: Environnement (development, staging, production) - `LOG_LEVEL`: Niveau de log (DEBUG, INFO, WARN, ERROR) ## Prochaines Étapes - ✅ PR5 complétée - ⏭️ PR6: Quick wins (MOD-P2-004, MOD-P2-010, MOD-P3-001, MOD-P3-002) --- **Statut**: ✅ **READY FOR REVIEW** **Effort**: ~6h (comme estimé dans audit: 4h + 1h + 1h) **Breaking Changes**: Aucun