Aller au contenu

Prometheus

Prometheus est le puits de métriques unique de PerfShop. Il scrape trois cibles toutes les 5 secondes, conserve les séries temporelles pendant 7 jours, et alimente les datasources de Grafana ainsi que le panneau de service-graphs/span-metrics produit par Tempo.

Source de vérité

Cette page est tirée de prometheus/prometheus.yml et des command: du service prometheus dans les fichiers compose.

Configuration globale

global:
  scrape_interval: 15s        # défaut, surchargé par chaque job à 5s
  evaluation_interval: 15s    # défaut, pour les rules

Le service Prometheus est lancé avec ces options de ligne de commande explicites :

--config.file=/etc/prometheus/prometheus.yml
--storage.tsdb.path=/prometheus
--storage.tsdb.retention.time=7d
--storage.tsdb.retention.size=5GB
--web.console.libraries=/usr/share/prometheus/console_libraries
--web.console.templates=/usr/share/prometheus/consoles
--web.enable-remote-write-receiver
--web.enable-lifecycle
Option Effet
--storage.tsdb.retention.time=7d Suppression automatique des séries de plus de 7 jours
--storage.tsdb.retention.size=5GB Cap dur sur la taille du TSDB
--web.enable-remote-write-receiver Active l'endpoint /api/v1/write — utilisé par Tempo (metrics_generator) pour pousser ses métriques de span-metrics et service-graphs
--web.enable-lifecycle Active /-/reload et /-/quit pour rechargement à chaud sans restart

Le port management interne est 9090, exposé sur le port hôte 9091 par défaut (variable PROMETHEUS_HTTP_PORT).

Cibles scrapées

PerfShop déclare trois jobs Prometheus, tous avec un scrape_interval: 5s (plus agressif que le défaut global de 15 s, pour permettre une observation fine en temps réel pendant les démonstrations chaos).

flowchart LR
  PROM["prometheus<br/>(9090 interne)"]

  subgraph t1["Job perfshop-backend"]
    APP["perfshop-app:9090<br/>/actuator/prometheus"]
  end

  subgraph t2["Job perfshop-docker"]
    MON["perfshop-monitoring:3001<br/>/metrics"]
  end

  subgraph t3["Job jmeter"]
    JM["perfshop-jmeter:9270<br/>(actif pendant un tir uniquement)"]
  end

  PROM -->|scrape 5s| APP
  PROM -->|scrape 5s| MON
  PROM -->|scrape 5s| JM

Job perfshop-backend

- job_name: 'perfshop-backend'
  static_configs:
    - targets: ['perfshop-app:9090']
  metrics_path: '/actuator/prometheus'
  scrape_interval: 5s

C'est le job principal. Il scrape l'endpoint Spring Boot Actuator exposé par Micrometer sur le port management 9090 (séparé du port applicatif 8080 — c'est volontaire, pour ne pas mélanger trafic métier et trafic d'observabilité). Toutes les métriques JVM, HTTP, JDBC, Tomcat, et les compteurs custom du chaos sont produits par ce seul endpoint.

Les principales familles de métriques scrapées :

Famille Préfixe / nom Origine
HTTP serveur http_server_requests_seconds_* Micrometer auto-config Spring Boot Web
JVM mémoire jvm_memory_used_bytes, jvm_memory_max_bytes, jvm_memory_committed_bytes Micrometer JVM binder
JVM threads jvm_threads_live_threads, jvm_threads_daemon_threads, jvm_threads_peak_threads, jvm_threads_states_threads Micrometer JVM binder
JVM GC jvm_gc_pause_seconds_count, jvm_gc_pause_seconds_sum Micrometer JVM binder
Tomcat tomcat_threads_busy_threads, tomcat_threads_current_threads, tomcat_threads_config_max_threads Micrometer Tomcat binder (activé via management.metrics.enable.tomcat=true)
HikariCP hikaricp_connections_active, _idle, _max, _pending, _acquire_seconds_* Micrometer HikariCP binder, label pool="PerfShopHikariPool"
Process process_cpu_usage, process_uptime_seconds, process_files_open_files Micrometer process binder
Chaos custom chaos_intensity{type="cpu|memory|thread_pool|db_pool|slow_query|deadlock|network"}, chaos_functional_level, chaos_functional_f4_corruption Compteurs custom déclarés dans les services chaos du backend

L'activation de l'histogramme HTTP est faite dans application.yml :

management:
  metrics:
    distribution:
      percentiles-histogram:
        http.server.requests: true

Sans cette ligne, les requêtes histogram_quantile() sur http_server_requests_seconds_bucket ne fonctionneraient pas (les buckets ne seraient pas exportés).

Job perfshop-docker

- job_name: 'perfshop-docker'
  static_configs:
    - targets: ['perfshop-monitoring:3001']
  metrics_path: '/metrics'
  scrape_interval: 5s

Le service perfshop-monitoring (Node + Express) interroge l'API Docker via le socket Unix monté en bind mount, calcule les statistiques CPU/RAM/réseau/I/O des principaux containers, et les expose au format Prometheus sur sa propre route /metrics. Voir dashboard-html.md pour le détail.

Les métriques produites par ce job utilisent toutes le préfixe docker_container_ :

Métrique Type Description
docker_container_cpu_percent{container="..."} gauge Pourcentage CPU calculé (cpuDelta / sysDelta) × numCpus × 100
docker_container_mem_usage_bytes{container="..."} gauge Mémoire utilisée (hors cache)
docker_container_mem_limit_bytes{container="..."} gauge Limite mémoire du container
docker_container_mem_percent{container="..."} gauge Pourcentage mémoire utilisée
docker_container_net_rx_bytes{container="..."} counter Octets reçus cumulés
docker_container_net_tx_bytes{container="..."} counter Octets envoyés cumulés
docker_container_io_read_bytes{container="..."} counter Octets lus disque cumulés
docker_container_io_write_bytes{container="..."} counter Octets écrits disque cumulés
docker_container_pids{container="..."} gauge Nombre de processus dans le container

Et des métriques navigateur poussées par chaos-agent.js depuis le frontend toutes les 2 secondes (POST /api/chaos/client-metrics), qui sont ré-exposées sur la route /metrics :

Métrique Description
perfshop_client_fps FPS mesuré dans le navigateur de l'étudiant
perfshop_client_heap_used_mb Heap JS utilisée (Mo)
perfshop_client_long_tasks_per_sec Long tasks (tâches > 50 ms) par seconde
perfshop_client_fetch_req_per_sec Requêtes fetch lancées par seconde
perfshop_client_dom_node_count Nombre de nœuds DOM
perfshop_client_cpu_worker_active 1 si un Web Worker CPU-intensive tourne dans le navigateur
perfshop_client_last_received_timestamp Timestamp Unix (ms) du dernier envoi reçu — utile pour calculer la fraîcheur

Containers surveillés

Le code Node de perfshop-monitoring ne surveille que quatre containers : perfshop-frontend, perfshop-app, perfshop-db, perfshop-monitoring. C'est volontaire — le dashboard HTML cible la chaîne « front → back → BDD » et le tableau Grafana « Vue Générale Containers » utilise le même job.

Job jmeter

- job_name: 'jmeter'
  static_configs:
    - targets: ['perfshop-jmeter:9270']
  scrape_interval: 5s
  honor_labels: true

Le container perfshop-jmeter est idle en permanence (tail -f /dev/null). Il n'expose rien sur le port 9270 entre les tirs. Quand un tir est lancé via perfshop-jmeter-ui, le plugin Prometheus listener de JMeter ouvre le port 9270 pendant la durée du tir et expose les métriques jmeter_*. Une fois le tir terminé, le port se ferme et Prometheus loggue des erreurs de scrape — c'est normal et attendu, et c'est documenté en commentaire dans prometheus.yml.

honor_labels: true permet aux labels exportés par JMeter (notamment label="..." qui correspond au nom du sampler) de ne pas être écrasés par les labels du job Prometheus.

Métriques exposées par le plugin JMeter Prometheus listener :

Métrique Description
jmeter_threads{state="active|started|finished"} Threads virtuels (vUsers) actifs / démarrés / terminés
jmeter_transactions_total{label="..."} Compteur cumulé de transactions par sampler
jmeter_response_time{quantile="0.5|0.95|0.99",label="..."} Quantiles de latence par sampler
jmeter_response_time_count{label="..."} Compteur d'échantillons par sampler
jmeter_response_time_sum{label="..."} Somme cumulée des latences (pour calcul de moyenne)
jmeter_success_ratio_success{label="..."} Compteur de succès
jmeter_success_ratio_failure{label="..."} Compteur d'échecs

Exemples de requêtes PromQL

Toutes les requêtes ci-dessous sont extraites des dashboards Grafana réellement livrés dans grafana/dashboards/{eleves,formateurs}/*.json. Elles sont donc à la fois pédagogiques et représentatives de l'usage réel.

1. Latence HTTP percentile p95 — toutes routes confondues

histogram_quantile(
  0.95,
  sum(rate(http_server_requests_seconds_bucket{job="perfshop-backend"}[5m])) by (le)
) * 1000

C'est la requête de référence pour observer la latence globale du backend. Le * 1000 convertit les secondes en millisecondes. La fenêtre [5m] est suffisamment large pour absorber les variations courtes, tout en restant réactive.

Variantes : 0.50 pour la médiane, 0.99 pour le p99. Le panel « Temps de réponse HTTP » utilise les trois en parallèle.

2. Taux d'erreur HTTP 5xx (en pourcentage)

sum(rate(http_server_requests_seconds_count{job="perfshop-backend",outcome="SERVER_ERROR"}[5m]))
/
sum(rate(http_server_requests_seconds_count{job="perfshop-backend"}[5m]))
* 100

Utilise le label outcome produit par Spring Boot Actuator (SUCCESS, CLIENT_ERROR, SERVER_ERROR, INFORMATIONAL, REDIRECTION, UNKNOWN).

3. Heap JVM utilisé (somme de tous les pools heap)

sum(jvm_memory_used_bytes{job="perfshop-backend",area="heap"})

area="heap" filtre les pools mémoire heap (Eden, Survivor, Old Gen). Pour la heap maximale :

sum(jvm_memory_max_bytes{job="perfshop-backend",area="heap"})

4. Pool HikariCP — connexions actives vs max

hikaricp_connections_active{job="perfshop-backend"}
hikaricp_connections_idle{job="perfshop-backend"}
hikaricp_connections_max{job="perfshop-backend"}
hikaricp_connections_pending{job="perfshop-backend"}

Les quatre métriques sont superposées dans le panel « Connexions BDD — État du pool HikariCP » du dashboard Backend Élève. Quand pending > 0, c'est qu'on attend une connexion — symptôme typique d'une exhaustion du pool, déclenchée par le chaos backend db_pool.

5. Latence d'acquisition d'une connexion BDD

rate(hikaricp_connections_acquire_seconds_sum{pool="PerfShopHikariPool"}[1m])
/
rate(hikaricp_connections_acquire_seconds_count{pool="PerfShopHikariPool"}[1m])
* 1000

Calcule la moyenne en millisecondes du temps passé à attendre une connexion HikariCP. Le label pool="PerfShopHikariPool" vient du nom configuré dans application.yml (spring.datasource.hikari.pool-name).

6. Threads HTTP Tomcat — occupés vs configurés

tomcat_threads_busy_threads{job="perfshop-backend"}
tomcat_threads_current_threads{job="perfshop-backend"}
tomcat_threads_config_max_threads{job="perfshop-backend"}

Les trois courbes ensemble : busy ≤ current ≤ config_max. Quand busy colle à config_max, c'est l'exhaustion du pool de threads HTTP — déclenchée par le chaos backend thread_pool.

7. Débit de requêtes 2xx vs 5xx vs 4xx

rate(http_server_requests_seconds_count{job="perfshop-backend",status=~"2.."}[1m])
rate(http_server_requests_seconds_count{job="perfshop-backend",status=~"5.."}[1m])
rate(http_server_requests_seconds_count{job="perfshop-backend",status=~"4.."}[1m])

Utilise les regex sur le label status. Les trois séries sont empilées dans le panel « Débit requêtes HTTP » pour visualiser le ratio.

8. Intensité courante des chaos (type par type)

chaos_intensity{type="cpu"}
chaos_intensity{type="memory"}
chaos_intensity{type="thread_pool"}
chaos_intensity{type="db_pool"}
chaos_intensity{type="slow_query"}
chaos_intensity{type="deadlock"}
chaos_intensity{type="network"}

C'est une gauge custom déclarée par le service ChaosService du backend. Sa valeur (entre 0 et 100, ou 0 et le niveau max) reflète l'intensité courante de chaque chaos backend. Le panel Formateur « Évolution temporelle des anomalies chaos » superpose les sept séries pour donner une vue globale de ce qui est actif.

Bonus — comptage des opérations instrumentées

count(count by (uri) (http_server_requests_seconds_count{job="perfshop-backend"}))

Retourne le nombre d'URIs distinctes connues par Spring Boot. Utile pour confirmer que de nouveaux endpoints ont bien été instrumentés après une mise à jour du backend.

Erreurs de scrape attendues

Le job jmeter clignote en rouge entre les tirs — c'est normal

Tant qu'aucun tir JMeter n'est en cours, le port 9270 n'est ouvert par aucun process — Prometheus loggue donc une erreur de scrape pour cette cible. C'est intentionnel et documenté en commentaire dans prometheus.yml. Si vous voulez masquer ces erreurs en démo, désactivez temporairement le job dans Prometheus, ou ignorez la série dans Grafana.

Endpoints utiles côté Prometheus

Endpoint Usage
http://localhost:9091/ UI Prometheus
http://localhost:9091/targets État des cibles scrapées
http://localhost:9091/graph Console de requêtage PromQL
http://localhost:9091/api/v1/write Endpoint remote-write (utilisé par Tempo)
http://localhost:9091/-/reload Recharge la configuration sans restart
http://localhost:9091/-/healthy Healthcheck

Pour aller plus loin