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

194 lines
5.8 KiB
Markdown

# 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é
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# É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**:
```bash
# 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é**:
```bash
telnet <service-host> <service-port>
# ou
nc -zv <service-host> <service-port>
```
2. **Vérifier firewall/routing**:
```bash
traceroute <service-host>
```
3. **Vérifier DNS**:
```bash
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):
```bash
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):
```go
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