--- title: 'Monitoring Stack : Prometheus + Grafana' url: https://blog.guigpap.com/fr/infrastructure/monitoring-stack/ url_md: https://blog.guigpap.com/fr/infrastructure/monitoring-stack.md category: infrastructure date: '2026-01-20' maturite: production techno: - prometheus - grafana - docker application: - monitoring - infrastructure --- # Monitoring Stack : Prometheus + Grafana > Observabilité complète avec collecte de métriques, dashboards et alertes automatisées ## 1. Quoi ? — Définition et contexte La **Monitoring Stack** assure l'observabilité de toute l'infrastructure. Elle collecte les métriques système et applicatives, les visualise via des dashboards, et déclenche des alertes en cas d'anomalie. ### Composants | Service | Port | Limite mémoire | Rôle | |---------|------|----------------|------| | **Prometheus** | 9090 | 2 GB | Collecte et stockage des métriques (mode pull) | | **Grafana** | 3000 | 1 GB | Visualisation et dashboards | | **Alertmanager** | 9093 | 512 MB | Routage et groupement des alertes | | **Node Exporter** | 9100 | 256 MB | Métriques système (CPU, RAM, disque) | | **Docker Exporter** | 9487 | 256 MB | Métriques par container (CPU, RAM, état) | | **OTEL Collector** | 4317/4318 (in), 8889 (scrape) | 512 MB | Ingestion télémétrie Claude Code | > **Note - Mode pull** > > **Prometheus** fonctionne en mode "pull" : il interroge régulièrement (scrape) les services pour récupérer leurs métriques. C'est Prometheus qui va chercher les données, pas les services qui les envoient. ### Architecture visuelle ```mermaid flowchart TD subgraph Scrape["Scrape targets"] direction LR NE["Node Exporter · host:9100"] DE["Docker Exporter · host:9487"] OT["OTEL Collector · host:8889"] DEN["Docker Engine · host:9323"] end subgraph Prom["Prometheus · :9090"] direction TB P1["Scrape toutes les 15s"] P2["Évalue les règles d'alerte"] P3["Stocke 15 jours / 5 GB max"] end subgraph AM["Alertmanager · :9093"] direction TB A1["Groupe alerts"] A2["Route → N8N"] end subgraph Graf["Grafana · :3000"] direction TB G1["Linux System"] G2["Docker Containers"] G3["Claude Code"] end Hook["N8N webhook · /webhook/prometheus/alert"] Tg["Notification Hub → Telegram"] Scrape --> Prom Prom --> AM Prom --> Graf AM --> Hook Hook --> Tg ``` --- ## 2. Pourquoi ? — Enjeux et motivations ### Problèmes résolus par le monitoring | Problème | Sans monitoring | Avec monitoring | |----------|-----------------|-----------------| | **Container crash** | Découvert par un utilisateur | Alerte immédiate | | **Disque plein** | Service inaccessible | Anticipé avant saturation | | **Fuite mémoire** | OOM killer aléatoire | Tendance visible, action préventive | | **Coûts Claude** | Surprise en fin de mois | Suivi en temps réel | ### Alertes les plus utiles en pratique | Alerte | Déclenchée | Utilité constatée | |--------|------------|-------------------| | **ContainerDown** | Service crash | Détection rapide, restart manuel ou auto | | **Claude Code telemetry** | Sessions Claude | Suivi du temps passé et des tokens utilisés | | **DiskSpaceLow** | Espace disque < 15% | Prévention avant incident | | **HighMemoryUsage** | RAM > 85% | Non encore déclenchée (marge suffisante) | > **Tip - Télémétrie Claude Code** > > L'intégration OTEL permet de suivre les sessions Claude Code : tokens consommés, coût estimé, temps actif. Ces métriques alimentent les dashboards Grafana pour le suivi de productivité. --- ## 3. Comment ? — Mise en œuvre technique ### Configuration Prometheus ```yaml # prometheus/prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'node-exporter' static_configs: - targets: ['node-exporter:9100'] - job_name: 'docker-exporter' static_configs: - targets: ['docker-exporter:9487'] - job_name: 'docker-engine' static_configs: - targets: ['host.docker.internal:9323'] - job_name: 'otel-collector' static_configs: - targets: ['otel-collector:8889'] ``` > **Note - cAdvisor retiré (audit sécurité 2026-02-20)** > > cAdvisor était utilisé historiquement pour les métriques per-container, mais il a été retiré : (1) cassé sur Docker 29+ avec overlayfs, (2) risque de sécurité (container privilégié avec `rootfs` + socket Docker). Les métriques per-container viennent maintenant de **docker-exporter**, et les compteurs globaux du daemon viennent des **Docker Engine metrics** (`host.docker.internal:9323`). ### Rétention des données ```yaml # Dans docker-compose.yaml, commande Prometheus command: - '--storage.tsdb.retention.time=15d' - '--storage.tsdb.retention.size=5GB' ``` > **Note - Dimensionnement** > > 15 jours et 5 GB suffisent pour une infrastructure personnelle. Pour des besoins d'historique plus long, considérez Thanos ou Victoria Metrics. ### Règles d'alerte ```yaml # prometheus/alerts.yml groups: - name: infrastructure rules: - alert: HighMemoryUsage expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85 for: 5m labels: severity: warning annotations: summary: "Mémoire haute sur {{ $labels.instance }}" description: "Usage mémoire: {{ $value | printf \"%.1f\" }}%" - alert: HighCPUUsage expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m labels: severity: warning - alert: DiskSpaceLow expr: (1 - (node_filesystem_avail_bytes{fstype!="tmpfs"} / node_filesystem_size_bytes)) * 100 > 85 for: 5m labels: severity: critical - alert: ContainerDown expr: absent(container_last_seen{name!=""}) for: 1m labels: severity: critical - alert: ServiceDown expr: up == 0 for: 1m labels: severity: critical ``` ### Alertmanager → N8N ```yaml # alertmanager/alertmanager.yml global: resolve_timeout: 5m route: receiver: 'n8n' group_by: ['alertname', 'severity'] group_wait: 30s group_interval: 5m repeat_interval: 4h receivers: - name: 'n8n' webhook_configs: - url: 'http://n8n:5678/webhook/prometheus/alert' send_resolved: true ``` Le [Notification Hub](/fr/workflows/notification-hub/) analyse la sévérité pour router les alertes : critiques → Telegram immédiat, warnings → regroupés. ### Claude Code Metrics (OTEL) Configuration Claude Code pour exporter la télémétrie : ```json // ~/.claude/settings.json { "env": { "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "OTEL_METRICS_EXPORTER": "otlp", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318", "OTEL_SERVICE_NAME": "claude-code" } } ``` | Métrique | Description | |----------|-------------| | `claude_code_token_usage_tokens_total` | Tokens par modèle et type | | `claude_code_cost_usage_USD_total` | Coût cumulé en USD | | `claude_code_active_time_seconds_total` | Temps actif | | `claude_code_lines_of_code_count_total` | Lignes modifiées | ### Exemples PromQL ```promql # CPU usage percentage 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) # Memory usage percentage (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 # Disk usage percentage (1 - (node_filesystem_avail_bytes{fstype!="tmpfs"} / node_filesystem_size_bytes)) * 100 # Container memory usage (top 5) topk(5, container_memory_usage_bytes{name!=""}) # Claude Code tokens total by model sum(claude_code_token_usage_tokens_total) by (model) # Claude Code cost USD sum(claude_code_cost_usage_USD_total) ``` ### Dashboards Grafana | Dashboard | Métriques | |-----------|-----------| | **Linux System** | CPU, RAM, disque, réseau, load average | | **Docker Containers** | CPU/RAM par conteneur, I/O, restarts | | **Claude Code** | Tokens, coûts, temps actif, lignes de code | --- ## 4. Et si ? — Perspectives et limites ### Intégration télémétrie Claude Code → Odoo Le pipeline complet va plus loin que l'observabilité brute : un hook `SessionEnd` côté machine de dev envoie les métadonnées de session à N8N, qui interroge Prometheus pour récupérer les métriques (tokens, coût, temps actif) et met à jour la tâche Odoo correspondante via XML-RPC. ``` ~/.claude (SessionEnd hook) │ ▼ POST /webhook/telemetry/session-end N8N Telemetry workflow │ Query Prometheus pour la session ▼ XML-RPC vers Odoo project.task (x_claude_time_total, x_claude_cost_total, …) ``` Voir [Claude Code Telemetry](/fr/workflows/claude-code-telemetry/) côté workflow. ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Rétention 15 jours** | Pas d'historique long terme | Exporter vers S3/Thanos si besoin | | **Pas de tracing** | Debugging workflows limité | Considérer Jaeger si besoin | | **OTEL Collector single** | SPOF pour la télémétrie | Acceptable pour usage personnel | ### Scénarios d'évolution **Si besoin d'historique > 15 jours** : - Déployer Thanos pour le stockage long terme - Ou exporter des snapshots vers S3 **Si besoin de tracer les workflows N8N** : - Ajouter Jaeger ou Tempo - Instrumenter N8N avec OTEL traces **Si le volume de métriques explose** : - Augmenter la rétention de Prometheus - Considérer Victoria Metrics (plus performant) ### Commandes de dépannage ```bash # Vérifier les targets Prometheus curl http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, health: .health}' # Tester la connectivité exporter docker exec prometheus wget -qO- http://node-exporter:9100/metrics | head # Vérifier les alertes actives curl http://localhost:9093/api/v1/alerts # Tester le webhook N8N curl -X POST http://n8n:5678/webhook/prometheus/alert \ -H "Content-Type: application/json" \ -d '{"alerts":[{"labels":{"alertname":"test"}}]}' ``` --- ## Pages liées ### Infrastructure - [Architecture VPS](/fr/infrastructure/architecture-vps/) — Vue d'ensemble - [Security Stack](/fr/infrastructure/security-stack/) — Caddy expose Grafana ### Workflows - [Notification Hub](/fr/workflows/notification-hub/) — Routage des alertes ### Référence - [Glossaire](/fr/reference/glossary/) — Prometheus, PromQL, OTEL, Scrape ## Metadonnees agent - Cet article est issu du blog GuiGPaP Lab. - Contexte global du blog: https://blog.guigpap.com/llms.txt - Contact auteur: https://odoo.guigpap.com/mon-cv - Licence: CC-BY-SA 4.0