6.7 KiB
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/queryde 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
-1si 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
LiveDatacentercorrespondant. - 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'à
ExpectedEndDatedu booking ou signal de kill. - A chaque tick (
interval), appelleCall()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
-
Race condition dans
Stream— Les variablesmets,bookIDS,booksont partagées entre la boucle principale et les goroutines lancées à chaque tick, sans synchronisation (pas de mutex). Siintervalest court, plusieurs goroutines peuvent écrire simultanément dansmetsetbookIDS. -
Race condition sur
Kill— La variable globaleKillest lue dans la boucle sans verrouillerLockKill. Le mutex n'est utilisé que pour l'écriture. -
Structs locales inutilisées —
MetricsSnapshotetMetric(lignes 22-31) sont déclarées localement mais le code utilisemodels.MetricsSnapshotetmodels.Metric. Code mort à nettoyer. -
Requête PromQL avec double placeholder — La requête filesystem (ligne 47) contient deux
%smaisqueryPrometheusne fait qu'un seulfmt.Sprintf(expr, namespace). Cela provoque un%!s(MISSING)dans la requête. Il faut passer le namespace deux fois ou réécrire la fonction. -
Pas de timeout HTTP —
http.Get()utilise le client par défaut sans timeout. Un Prometheus lent peut bloquer indéfiniment. -
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àqueryPrometheusetCallpour supporter les timeouts et l'annulation. - Utiliser un
http.Clientavec timeout au lieu dehttp.Get. - Protéger les accès concurrents dans
Streamavec unsync.Mutexsurmets/bookIDS. - Remplacer la variable globale
Killpar uncontext.WithCancelou 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 quememory_usage_bytes).kube_pod_status_phase— Phase du pod (Running, Pending, Failed...).container_oom_events_totaloukube_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_rangepermettrait 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.