veza/veza-backend-api/docs/runbooks/circuit_breaker_open.md
2025-12-16 11:23:49 -05:00

5.8 KiB

Runbook: Circuit Breaker Open

Signal

Alerte déclenchée:

  • VezaCircuitBreakerOpen - Circuit breaker en état OPEN depuis > 5 minutes

Symptômes observables:

  • Métrique: veza_circuit_breaker_state == 2 (2 = OPEN)
  • Logs: circuit breaker opened for [service_name]
  • Erreurs: Toutes les requêtes vers le service externe sont rejetées immédiatement
  • Endpoints affectés: OAuth, Stream service, autres dépendances externes

Hypothèses

  1. Service externe down - OAuth provider, Stream server, etc. ne répond plus
  2. Service externe lent - Timeouts répétés, service surchargé
  3. Réseau - Problème de connectivité vers service externe
  4. Configuration circuit breaker - Seuils trop stricts (peu probable)

Vérifications

1. Identifier le circuit breaker affecté

# Vérifier métriques Prometheus
curl -s "http://localhost:9090/api/v1/query?query=veza_circuit_breaker_state" | jq

# Exemple de réponse:
# {
#   "metric": {
#     "circuit_breaker_name": "oauth_service"
#   },
#   "value": [1234567890, "2"]
# }
# 2 = OPEN, 1 = HALF_OPEN, 0 = CLOSED

2. Vérifier logs application

# Chercher ouverture circuit breaker
grep -i "circuit breaker opened\|circuit breaker open" /var/log/veza-backend-api/*.log | tail -20

# Chercher erreurs service externe
grep -i "oauth\|stream.*error\|timeout" /var/log/veza-backend-api/*.log | tail -50

3. Tester service externe directement

# Pour OAuth service (exemple)
curl -v https://oauth-provider.example.com/health

# Pour Stream service (exemple)
curl -v http://stream-server:8082/health

# Vérifier timeout
timeout 5 curl http://<service-external>/health

4. Vérifier métriques circuit breaker

# Échecs consécutifs
curl -s "http://localhost:9090/api/v1/query?query=veza_circuit_breaker_consecutive_failures" | jq

# Total échecs
curl -s "http://localhost:9090/api/v1/query?query=veza_circuit_breaker_failures_total" | jq

# Requêtes rejetées
curl -s "http://localhost:9090/api/v1/query?query=veza_circuit_breaker_requests_total{result=\"rejected\"}" | jq

Actions Correctives

Si service externe down

  1. Vérifier santé service externe:

    • Consulter dashboard/monitoring du service externe
    • Vérifier logs du service externe
    • Contacter équipe responsable du service
  2. En attendant réparation:

    • Option A: Service peut fonctionner en mode dégradé (fonctionnalités optionnelles désactivées)
    • Option B: Si critique, mettre service en maintenance
  3. Documenter impact:

    • Quelles fonctionnalités sont affectées?
    • Combien d'utilisateurs impactés?

Si service externe lent

  1. Vérifier charge service externe:

    # Si accès monitoring
    curl http://<service-external>/metrics | grep cpu\|memory\|requests
    
  2. Augmenter timeout temporairement (si configurable):

    • Modifier timeout dans internal/services/circuit_breaker.go
    • ⚠️ Attention: Augmenter timeout peut masquer le problème
  3. Contacter équipe service externe:

    • Signaler latence élevée
    • Demander investigation

Si réseau

  1. Tester connectivité:

    telnet <service-host> <service-port>
    # ou
    nc -zv <service-host> <service-port>
    
  2. Vérifier firewall/routing:

    traceroute <service-host>
    
  3. Vérifier DNS:

    nslookup <service-host>
    dig <service-host>
    

Forcer réouverture circuit breaker (si nécessaire)

⚠️ DANGER: Ne forcer la réouverture que si le service externe est confirmé opérationnel.

Le circuit breaker se rouvrira automatiquement après le timeout configuré (généralement 60s). Pour forcer manuellement:

  1. Redémarrer application (force reset circuit breaker):

    sudo systemctl restart veza-backend-api
    # ou
    docker restart veza-backend-api
    
  2. Attendre timeout automatique:

    • Circuit breaker passe en HALF_OPEN après timeout
    • Si prochaine requête réussit → CLOSED
    • Si prochaine requête échoue → re-OPEN

Post-Mortem Notes

À documenter après résolution

  • Circuit breaker affecté: oauth_service / stream_service / autre
  • Cause racine: Service externe down / Lent / Réseau / Autre
  • Durée de l'incident: De [heure début] à [heure fin]
  • Impact: Fonctionnalités affectées, utilisateurs impactés
  • Actions prises: Liste des actions correctives
  • Actions préventives:
    • Améliorer monitoring service externe
    • Ajouter alertes côté service externe
    • Revoir configuration circuit breaker (seuils, timeout)
    • Implémenter fallback/retry logic

Métriques à surveiller post-incident

  • veza_circuit_breaker_state - Doit revenir à 0 (CLOSED)
  • veza_circuit_breaker_consecutive_failures - Doit revenir à 0
  • veza_circuit_breaker_requests_total{result="success"} - Doit augmenter
  • veza_circuit_breaker_requests_total{result="rejected"} - Doit s'arrêter d'augmenter

Configuration Circuit Breaker

Fichier: internal/services/circuit_breaker.go

Paramètres par défaut (sony/gobreaker):

  • MaxRequests: 3 (half-open state)
  • Interval: 60s (timeout avant réouverture)
  • Timeout: 60s (durée état OPEN)
  • ReadyToTrip: 5 échecs consécutifs → OPEN

Modification (si nécessaire):

cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
    MaxRequests: 3,
    Interval:    60 * time.Second,
    Timeout:     60 * time.Second,
    ReadyToTrip: func(counts gobreaker.Counts) bool {
        return counts.ConsecutiveFailures > 5
    },
})

Références

  • Métriques circuit breaker: internal/metrics/circuit_breaker.go
  • Service circuit breaker: internal/services/circuit_breaker.go
  • Documentation gobreaker: https://github.com/sony/gobreaker