Datacenter no more handle booking but is fully charged with Kube & minio allocate per NATS
This commit is contained in:
100
infrastructure/monitor/PROMETHEUS_ANALYSIS.md
Normal file
100
infrastructure/monitor/PROMETHEUS_ANALYSIS.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Analyse de `infrastructure/prometheus.go`
|
||||
|
||||
## Ce que fait le fichier
|
||||
|
||||
Ce fichier implémente un service de monitoring qui interroge une instance **Prometheus** pour collecter des métriques de conteneurs Kubernetes associés à une réservation (Booking).
|
||||
|
||||
### Structures de données
|
||||
|
||||
| Struct | Role |
|
||||
|---|---|
|
||||
| `MetricsSnapshot` | Snapshot de métriques associé à une origine (source). **Note : cette struct locale est déclarée mais jamais utilisée** — le code utilise en réalité `models.MetricsSnapshot` de oc-lib. |
|
||||
| `Metric` | Paire nom/valeur d'une métrique. **Même remarque** — le code utilise `models.Metric`. |
|
||||
| `PrometheusResponse` | Mapping de la réponse JSON de l'API Prometheus `/api/v1/query`. |
|
||||
|
||||
### Métriques collectées (`queriesMetrics`)
|
||||
|
||||
| # | Requête PromQL | Mesure |
|
||||
|---|---|---|
|
||||
| 1 | `rate(container_cpu_usage_seconds_total{namespace}[1m]) * 100` | Utilisation CPU (%) |
|
||||
| 2 | `container_memory_usage_bytes{namespace}` | Mémoire utilisée (bytes) |
|
||||
| 3 | `container_fs_usage_bytes / container_fs_limit_bytes * 100` | Utilisation disque (%) |
|
||||
| 4 | `DCGM_FI_DEV_GPU_UTIL{namespace}` | Utilisation GPU (NVIDIA DCGM) |
|
||||
| 5 | `rate(container_fs_reads_bytes_total[1m])` | Débit lecture disque (bytes/s) |
|
||||
| 6 | `rate(container_fs_writes_bytes_total[1m])` | Débit écriture disque (bytes/s) |
|
||||
| 7 | `rate(container_network_receive_bytes_total[1m])` | Bande passante réseau entrante (bytes/s) |
|
||||
| 8 | `rate(container_network_transmit_bytes_total[1m])` | Bande passante réseau sortante (bytes/s) |
|
||||
| 9 | `rate(http_requests_total[1m])` | Requêtes HTTP/s |
|
||||
| 10 | `rate(http_requests_total{status=~"5.."}[1m]) / rate(http_requests_total[1m]) * 100` | Taux d'erreur HTTP 5xx (%) |
|
||||
|
||||
Métriques commentées (non actives) : `system_load_average`, `system_network_latency_ms`, `app_mean_time_to_repair_seconds`, `app_mean_time_between_failure_seconds`.
|
||||
|
||||
### Méthodes
|
||||
|
||||
#### `queryPrometheus(promURL, expr, namespace) Metric`
|
||||
- Construit une requête GET vers `/api/v1/query` de Prometheus.
|
||||
- Injecte le namespace dans l'expression PromQL via `fmt.Sprintf`.
|
||||
- Parse la réponse JSON et extrait la première valeur du premier résultat.
|
||||
- Retourne `-1` si aucun résultat.
|
||||
|
||||
#### `Call(book, user, peerID, groups) (Booking, map[string]MetricsSnapshot)`
|
||||
- Charge la ressource de calcul (`ComputeResource`) liée au booking.
|
||||
- Pour chaque instance de la ressource, cherche le `LiveDatacenter` correspondant.
|
||||
- Lance en **goroutine** (parallèle) l'exécution de toutes les requêtes PromQL pour chaque datacenter ayant un `MonitorPath`.
|
||||
- Attend toutes les goroutines (`sync.WaitGroup`), puis retourne les métriques groupées par instance.
|
||||
|
||||
#### `Stream(bookingID, interval, user, peerID, groups, websocket)`
|
||||
- Boucle de monitoring en continu jusqu'à `ExpectedEndDate` du booking ou signal de kill.
|
||||
- A chaque tick (`interval`), appelle `Call()` dans une goroutine.
|
||||
- Envoie les métriques en temps réel via **WebSocket**.
|
||||
- Accumule les métriques en mémoire et les persiste dans le booking tous les `max` (100) cycles.
|
||||
- Supporte un mécanisme de kill via la variable globale `Kill`.
|
||||
|
||||
---
|
||||
|
||||
## Problemes et points d'attention
|
||||
|
||||
### Bugs potentiels
|
||||
|
||||
1. **Race condition dans `Stream`** — Les variables `mets`, `bookIDS`, `book` sont partagées entre la boucle principale et les goroutines lancées à chaque tick, **sans synchronisation** (pas de mutex). Si `interval` est court, plusieurs goroutines peuvent écrire simultanément dans `mets` et `bookIDS`.
|
||||
|
||||
2. **Race condition sur `Kill`** — La variable globale `Kill` est lue dans la boucle sans verrouiller `LockKill`. Le mutex n'est utilisé que pour l'écriture.
|
||||
|
||||
3. **Structs locales inutilisées** — `MetricsSnapshot` et `Metric` (lignes 22-31) sont déclarées localement mais le code utilise `models.MetricsSnapshot` et `models.Metric`. Code mort à nettoyer.
|
||||
|
||||
4. **Requête PromQL avec double placeholder** — La requête filesystem (ligne 47) contient deux `%s` mais `queryPrometheus` ne fait qu'un seul `fmt.Sprintf(expr, namespace)`. Cela provoque un **`%!s(MISSING)`** dans la requête. Il faut passer le namespace deux fois ou réécrire la fonction.
|
||||
|
||||
5. **Pas de timeout HTTP** — `http.Get()` utilise le client par défaut sans timeout. Un Prometheus lent peut bloquer indéfiniment.
|
||||
|
||||
6. **Pas de gestion d'erreur sur `WriteJSON`** — Si le WebSocket est fermé côté client, l'écriture échoue silencieusement.
|
||||
|
||||
### Améliorations possibles
|
||||
|
||||
#### Fiabilité
|
||||
- **Ajouter un `context.Context`** à `queryPrometheus` et `Call` pour supporter les timeouts et l'annulation.
|
||||
- **Utiliser un `http.Client` avec timeout** au lieu de `http.Get`.
|
||||
- **Protéger les accès concurrents** dans `Stream` avec un `sync.Mutex` sur `mets`/`bookIDS`.
|
||||
- **Remplacer la variable globale `Kill`** par un `context.WithCancel` ou un channel, plus idiomatique en Go.
|
||||
|
||||
#### Métriques supplémentaires envisageables
|
||||
- `container_cpu_cfs_throttled_seconds_total` — Throttling CPU (le container est bridé).
|
||||
- `kube_pod_container_status_restarts_total` — Nombre de restarts (instabilité).
|
||||
- `container_memory_working_set_bytes` — Mémoire réelle utilisée (exclut le cache, plus précis que `memory_usage_bytes`).
|
||||
- `kube_pod_status_phase` — Phase du pod (Running, Pending, Failed...).
|
||||
- `container_oom_events_total` ou `kube_pod_container_status_last_terminated_reason` — Détection des OOM kills.
|
||||
- `kubelet_volume_stats_used_bytes` / `kubelet_volume_stats_capacity_bytes` — Utilisation des PVC.
|
||||
- `DCGM_FI_DEV_MEM_COPY_UTIL` — Utilisation mémoire GPU.
|
||||
- `DCGM_FI_DEV_GPU_TEMP` — Température GPU.
|
||||
- `node_cpu_seconds_total` / `node_memory_MemAvailable_bytes` — Métriques au niveau du noeud (vue globale).
|
||||
|
||||
#### Architecture
|
||||
- **Range queries** (`/api/v1/query_range`) — Actuellement seul l'instant query est utilisé. Pour le streaming sur une période, `query_range` permettrait de récupérer des séries temporelles complètes et de calculer des moyennes/percentiles.
|
||||
- **Labels dans les résultats** — Actuellement seule la première série est lue (`Result[0]`). On perd l'information si plusieurs pods/containers matchent. Agréger ou renvoyer toutes les séries.
|
||||
- **Noms de métriques lisibles** — Mapper les expressions PromQL vers des noms humains (`cpu_usage_percent`, `memory_bytes`, etc.) au lieu de stocker l'expression brute comme nom.
|
||||
- **Health check Prometheus** — Ajouter une méthode pour vérifier que Prometheus est accessible (`/-/healthy`).
|
||||
|
||||
---
|
||||
|
||||
## Résumé
|
||||
|
||||
Le fichier est **fonctionnel** pour un cas d'usage basique (collecte one-shot + streaming WebSocket), mais présente des **race conditions** dans `Stream`, un **bug sur la requête filesystem** (double `%s`), et du **code mort**. Les améliorations prioritaires sont la correction des accès concurrents et l'ajout de timeouts HTTP.
|
||||
Reference in New Issue
Block a user