Monitoring & Observability Runbook
- Version:
1.0.0
- Date:
10 novembre 2025
- Stack:
Prometheus + Grafana + Loki + Alertmanager
📊 Stack de Monitoring
Composants :
Prometheus (http://vps-ip:9090) : Métriques time-series (30 jours)
Grafana (http://vps-ip:3001) : Dashboards et visualisation
Loki : Agrégation de logs (7 jours)
Alertmanager (http://vps-ip:9093) : Gestion des alertes
Node Exporter : Métriques système (CPU, RAM, disk, network)
PostgreSQL Exporter : Métriques database
Backend `/metrics` : Métriques applicatives (Actix-web)
🔍 Métriques Clés
API Backend
Métriques exposées : http://localhost:8080/metrics
# Requêtes HTTP
http_requests_total{method="GET",path="/api/v1/buildings",status="200"} 1234
http_request_duration_seconds_bucket{le="0.005"} 980
http_request_duration_seconds_bucket{le="0.01"} 1150
# Erreurs
http_requests_errors_total{status="500"} 3
# Database
db_connections_active 8
db_query_duration_seconds_sum 45.2
Système (Node Exporter)
# CPU
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# RAM
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
# Disk
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100
# Network
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])
PostgreSQL
# Connexions actives
pg_stat_activity_count
# Taille DB
pg_database_size_bytes{datname="koprogo_db"}
# Transactions
rate(pg_stat_database_xact_commit{datname="koprogo_db"}[5m])
rate(pg_stat_database_xact_rollback{datname="koprogo_db"}[5m])
🚨 Alertes Critiques
Alertes configurées (Alertmanager)
Haute priorité (PagerDuty + Slack + SMS) :
API Down :
up{job="koprogo-api"} == 0pendant 1 minuteDatabase Down :
up{job="postgresql"} == 0pendant 30 secondesDisk Full :
node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.1(< 10%)High Error Rate :
rate(http_requests_errors_total[5m]) > 10(> 10 erreurs/s)Memory Exhaustion :
node_memory_MemAvailable_bytes < 104857600(< 100MB disponible)
Priorité moyenne (Slack uniquement) :
Slow API :
histogram_quantile(0.99, http_request_duration_seconds) > 1(P99 > 1s)High CPU :
avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) < 0.2(> 80% usage)Database Connections High :
pg_stat_activity_count > 80(> 80 connexions)
Procédure d’alerte :
Notification reçue (Slack/SMS)
Accéder à Grafana pour visualiser
Consulter logs Loki pour contexte
Appliquer runbook correspondant (voir ci-dessous)
Documenter résolution dans #incidents
Post-mortem si critique
📈 Dashboards Grafana
Dashboards essentiels
1. API Overview :
Requêtes/seconde par endpoint
Latence P50/P95/P99
Taux d’erreurs (2xx, 4xx, 5xx)
Top endpoints les plus lents
2. System Health :
CPU, RAM, Disk, Network
Nombre de processus
Load average (1m, 5m, 15m)
Disk I/O
3. PostgreSQL Performance :
Connexions actives/idle
Cache hit ratio (devrait être > 90%)
Taille DB + croissance
Slow queries (> 1s)
4. Business Metrics :
Nouveaux utilisateurs/jour
Dépenses créées/validées
Taux de paiement à temps
Utilisateurs actifs (DAU/MAU)
🔧 Runbooks par Alerte
API Down
Alerte : up{job="koprogo-api"} == 0
# 1. Vérifier si le service tourne
ssh root@prod-server "systemctl status koprogo-api"
# 2. Consulter logs récents
ssh root@prod-server "journalctl -u koprogo-api -n 100 --no-pager"
# 3. Redémarrer si crash
ssh root@prod-server "systemctl restart koprogo-api"
# 4. Vérifier health endpoint
curl http://prod-server:8080/health
# 5. Si échec persistant : disaster recovery
# Voir docs/operations/disaster-recovery.rst
Causes fréquentes :
Panic Rust (bug application)
Database unreachable
OOM killer (mémoire insuffisante)
Database Down
Alerte : up{job="postgresql"} == 0
# 1. Vérifier statut PostgreSQL
ssh root@prod-server "systemctl status postgresql"
# 2. Consulter logs
ssh root@prod-server "tail -n 100 /var/log/postgresql/postgresql-15-main.log"
# 3. Tenter redémarrage
ssh root@prod-server "systemctl restart postgresql"
# 4. Si corruption : disaster recovery
# Voir docs/operations/disaster-recovery.rst (Scénario 1)
Disk Full
Alerte : node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.1
# 1. Identifier ce qui consomme l'espace
ssh root@prod-server "du -sh /* | sort -h | tail -n 20"
# 2. Nettoyer logs anciens
ssh root@prod-server "find /var/log -name '*.log' -mtime +30 -delete"
ssh root@prod-server "journalctl --vacuum-time=7d"
# 3. Nettoyer Docker
ssh root@prod-server "docker system prune -af --volumes"
# 4. Nettoyer backups locaux
ssh root@prod-server "find /var/backups -name '*.gpg' -mtime +7 -delete"
# 5. Si insuffisant : étendre volume ou migrer vers serveur plus grand
Slow API (P99 > 1s)
# 1. Identifier endpoints lents (Grafana)
# Dashboard "API Overview" → Panel "Slowest Endpoints"
# 2. Consulter logs applicatifs
ssh root@prod-server "grep 'duration_ms' /var/log/koprogo/api.log | awk '{if ($5 > 1000) print}'"
# 3. Vérifier slow queries PostgreSQL
ssh root@prod-server "sudo -u postgres psql koprogo_db -c \"SELECT query, mean_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;\""
# 4. Ajouter index si requêtes non optimisées
# Créer migration SQLx
# 5. Si charge trop élevée : scale horizontalement
# Ajouter instance load-balanced
📝 Logs (Loki)
Requêtes LogQL utiles
Erreurs backend :
{job="koprogo-api"} |= "ERROR" | json
Requêtes lentes :
{job="koprogo-api"} | json | duration_ms > 1000
Échecs d’authentification :
{job="koprogo-api"} |= "401" | json | path="/api/v1/auth/login"
Database errors :
{job="postgresql"} |= "ERROR" | logfmt
🔐 Sécurité Monitoring
Intrusion Detection (Suricata)
Logs : /var/log/suricata/eve.json
Alertes :
SQL Injection attempts
XSS attempts
Path traversal
Port scanning
Dashboard Grafana : “Security Events”
fail2ban
Jails actifs :
SSH brute-force (10 tentatives → ban 10 minutes)
API abuse (100 req/min → ban 1 heure)
PostgreSQL brute-force
Vérifier bans :
sudo fail2ban-client status sshd
sudo fail2ban-client status api-abuse
CrowdSec
Community threat intelligence :
# Lister décisions actives
sudo cscli decisions list
# Métriques
sudo cscli metrics
📞 Contacts Escalation
Niveaux :
L1 - Monitoring automatique : Alertmanager → Slack #alerts
L2 - Astreinte SRE : PagerDuty → +32 XXX XX XX XX
L3 - Lead Engineer : +32 XXX XX XX XX (incidents critiques uniquement)
L4 - CTO : +32 XXX XX XX XX (disaster recovery, incidents de sécurité)
—
Version : 1.0.0 | Dernière mise à jour : 10 novembre 2025