Surveillance Ollama en production : logs et alertes Prometheus

Trois heures dix-sept du matin. Alerte rouge Slack : Ollama API timeout - service unavailable. Le système de support client est en ligne depuis deux semaines, avec des centaines d’appels par jour. Au déploiement, seuls des logs basiques étaient configurés — aucune surveillance ni alerte. Mémoire GPU saturée ? Processus planté ? Problème réseau ? Aucune visibilité. Retour à la normale seulement à six heures.
L’absence de surveillance en est l’une des causes principales.
Cet article partage une solution complète — de la configuration des logs à Prometheus + Grafana, jusqu’aux alertes AlertManager — avec des fichiers de config prêts à copier. En suivant ce guide, vous pouvez mettre en place une surveillance de niveau production en environ 30 minutes.
Les défis de la surveillance en production
Ollama n’est pas un service web ordinaire. C’est un « gros consommateur de ressources ». Chaque modèle chargé occupe 4 à 16 Go de mémoire (données Markaicode). Et le cold start — chargement du disque vers la mémoire — prend 10 à 30 secondes. Si le service redémarre après une panne, l’utilisateur attend une demi-minute avant toute réponse.
Les pièges que j’ai rencontrés :
Fuites mémoire et épuisement GPU. Après une longue exécution, Ollama oublie parfois de libérer la VRAM. J’ai vu une machine 24 Go de VRAM ne plus avoir que 2 Go disponibles après deux jours — toutes les nouvelles requêtes refusées. Le pire : je ne savais pas ce qui se passait jusqu’aux plaintes utilisateurs.
Accumulation de la file d’attente. L’inférence est lente — 5 à 20 secondes par requête. Des dizaines de requêtes simultanées font gonfler la file jusqu’au timeout. Comment savoir si la file s’accumule ? On devine.
Latence de chargement des modèles. En multi-modèles, le temps de chargement reste une boîte noire. L’utilisateur ne comprend pas la lenteur, vous non plus.
L’objectif de la surveillance est donc clair : disponibilité (le processus tourne-t-il ?), performance (quelle latence ?), utilisation des ressources (combien de VRAM reste-t-il ?), taux d’erreur (combien de requêtes échouent ?). Maîtriser ces quatre dimensions, c’est retrouver la sérénité.
Pour le choix d’outils, j’ai testé plusieurs combinaisons. Prometheus + Grafana suffit aux petites équipes ; pour tracer prompts et réponses LLM, Langfuse est excellent ; en entreprise, SigNoz basé sur OpenTelemetry unifie logs, métriques et traces. Je me concentre ici sur Prometheus — la base la plus universelle.
Configuration des logs et optimisation systemd
Démarrer Ollama est facile ; le faire tourner de façon stable commence par des logs corrects. J’ai déjà cherché des traces après un incident — rien n’était enregistré, ou le fichier faisait des dizaines de Go et a saturé le disque.
Configuration du service systemd
Avec l’installation officielle, un service systemd est créé automatiquement. La config par défaut est minimaliste — en production, il faut l’enrichir :
# /etc/systemd/system/ollama.service
[Unit]
Description=Ollama Service
After=network.target
[Service]
Type=simple
User=ollama
Group=ollama
# Répertoire de travail
WorkingDirectory=/usr/share/ollama
# Variables d'environnement
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_MODELS=/data/ollama/models"
Environment="OLLAMA_DEBUG=1"
Environment="OLLAMA_LOG_FORMAT=json"
# Limites de ressources (ajustez selon votre matériel)
LimitNOFILE=65535
LimitNPROC=4096
MemoryMax=32G
# Stratégie de redémarrage automatique
Restart=always
RestartSec=10
# Commande de démarrage
ExecStart=/usr/local/bin/ollama serve
# Sortie standard et erreurs
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Quelques points d’expérience :
Restart=always et RestartSec=10 : redémarrage automatique après crash, avec 10 s de pause pour laisser le système respirer. Sans cet intervalle, après un épuisement mémoire, Ollama redémarre en boucle et les logs explosent.
MemoryMax=32G : limite la mémoire max d’Ollama. Essentiel si d’autres services tournent sur la machine. Sans limite, j’ai vu Ollama consommer 64 Go — impossible de se connecter en SSH.
OLLAMA_DEBUG=1 et OLLAMA_LOG_FORMAT=json : le mode debug en production facilite le diagnostic. Le format JSON permet un parsing automatisé.
Après modification, n’oubliez pas :
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo systemctl enable ollama # démarrage au boot
Logs en déploiement Docker
Avec Docker, la gestion des logs est encore plus piégeuse. Par défaut, les logs vont dans /var/lib/docker/containers/ sans limite de taille.
Ma configuration docker-compose :
# docker-compose.yml
version: '3.8'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
ports:
- "11434:11434"
volumes:
- ./ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0:11434
- OLLAMA_DEBUG=1
deploy:
resources:
limits:
memory: 32G
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
max-size: "100m" : 100 Mo max par fichier. max-file: "5" : 5 fichiers conservés. Total max 500 Mo — suffisant sans saturer le disque.
Niveaux de log
Variables d’environnement Ollama :
| Variable | Description | Recommandation production |
|---|---|---|
OLLAMA_DEBUG | 1 pour activer les logs détaillés | Recommandé |
OLLAMA_LOG_LEVEL | Niveau (INFO/DEBUG/WARN) | INFO ou DEBUG |
OLLAMA_LOG_FORMAT | Format (text/json) | JSON |
Je laisse généralement DEBUG activé — l’espace disque coûte moins cher que des heures de diagnostic.
journalctl en pratique
Une fois configuré, consultez les logs avec journalctl :
# Logs en temps réel
sudo journalctl -u ollama -f
# 100 dernières lignes
sudo journalctl -u ollama -n 100
# Logs du jour
sudo journalctl -u ollama --since today
# Recherche par mot-clé
sudo journalctl -u ollama | grep -i "error"
# Export vers un fichier
sudo journalctl -u ollama --since "2026-04-12 00:00:00" > ollama-debug.log
Astuce avec logs JSON : filtrez avec jq :
sudo journalctl -u ollama -o json | jq 'select(.level=="error")'
Seuls les logs d’erreur — sans fouiller dans des pages d’INFO.
Surveillance Prometheus + Grafana
Les logs servent à l’analyse a posteriori ; la surveillance est l’œil qui prévient. Prometheus + Grafana, je l’utilise depuis plus de deux ans — la config est un peu lourde, mais c’est stable et la communauté est riche.
Déploiement ollama-exporter
Ollama n’expose pas directement de métriques Prometheus — il faut un exporter. J’utilise frcooper/ollama-exporter : peu d’étoiles (36), mais fonctionnel.
Deux modes : binaire direct ou Docker. Je recommande Docker :
# Ajouter le service exporter dans docker-compose.yml
services:
ollama-exporter:
image: frazco/ollama-exporter:latest
container_name: ollama-exporter
restart: always
ports:
- "9101:9101"
environment:
- OLLAMA_HOST=ollama:11434 # pointe vers le conteneur ollama
depends_on:
- ollama
Configuration Prometheus :
# prometheus.yml
global:
scrape_interval: 30s # intervalle d'échantillonnage, Markaicode recommande 30 s
evaluation_interval: 30s
scrape_configs:
- job_name: 'ollama-exporter'
static_configs:
- targets: ['ollama-exporter:9101']
labels:
instance: 'ollama-prod'
# Surveillance GPU (NVIDIA)
- job_name: 'nvidia-gpu'
static_configs:
- targets: ['localhost:9835']
Ajoutez Prometheus au docker-compose :
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: always
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
volumes:
prometheus_data:
Métriques clés
Métriques collectées par ollama-exporter — les plus importantes :
| Métrique | Description | Point d’attention |
|---|---|---|
ollama_requests_total | Nombre total de requêtes | Calcul du taux d’erreur |
ollama_requests_failed | Requêtes échouées | Surveillance directe |
ollama_model_load_duration_seconds | Durée de chargement modèle | Performance cold start |
ollama_request_duration_seconds | Temps de réponse | Latence P95/P99 |
ollama_tokens_per_second | Vitesse d’inférence | Débit |
Métriques système (avec node-exporter) :
- Utilisation CPU :
node_cpu_seconds_total - Utilisation mémoire :
node_memory_MemAvailable_bytes - Trafic réseau :
node_network_receive_bytes_total
Configuration surveillance GPU
Le GPU est le cœur d’un service LLM — la surveillance est indispensable. J’utilise nvidia_gpu_prometheus_exporter :
# Installer NVIDIA GPU exporter
docker run -d \
--name nvidia-exporter \
--restart always \
-p 9835:9835 \
--gpus all \
nvidia/gpu-prometheus-exporter:latest
Métriques clés :
nvidia_gpu_utilization: utilisation GPUnvidia_gpu_memory_used_bytes: VRAM utiliséenvidia_gpu_memory_free_bytes: VRAM restantenvidia_gpu_temperature: température GPU
En multi-GPU, les métriques portent le label gpu_id — affichage par carte dans Grafana.
Configuration du dashboard Grafana
Voici un JSON importable. Sauvegardez-le, puis Import Dashboard dans Grafana :
{
"dashboard": {
"title": "Ollama Production Monitor",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(ollama_requests_total[5m])",
"legendFormat": "Requests/sec"
}
],
"gridPos": {"x": 0, "y": 0, "w": 12, "h": 6}
},
{
"title": "Error Rate",
"type": "gauge",
"targets": [
{
"expr": "rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) * 100",
"legendFormat": "Error %"
}
],
"gridPos": {"x": 12, "y": 0, "w": 6, "h": 6}
},
{
"title": "GPU Memory Usage",
"type": "graph",
"targets": [
{
"expr": "nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes * 100",
"legendFormat": "GPU {{gpu_id}}"
}
],
"gridPos": {"x": 0, "y": 6, "w": 12, "h": 6}
},
{
"title": "Response Latency P95",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(ollama_request_duration_seconds_bucket[5m]))",
"legendFormat": "P95 Latency"
}
],
"gridPos": {"x": 12, "y": 6, "w": 6, "h": 6}
}
]
},
"overwrite": true
}
Disposition typique :
- En haut à gauche : courbe du débit de requêtes, pics visibles
- En haut à droite : jauge taux d’erreur, rouge au-delà de 5 %
- En bas à gauche : courbes VRAM multi-GPU
- En bas à droite : valeur latence P95
J’ajoute aussi un panneau Tokens/s pour comparer la vitesse d’inférence entre modèles.
Source de données Grafana
Après le démarrage du conteneur Grafana, configurez Prometheus :
- Connexion Grafana (admin/admin par défaut)
- Configuration -> Data Sources -> Add data source
- Choisir Prometheus, URL
http://prometheus:9090 - Save & Test
Avec docker-compose, les conteneurs communiquent par nom de service.
Règles d’alerte et configuration AlertManager
La surveillance montre les problèmes ; les alertes vous disent « agissez maintenant ». J’ai commis l’erreur de tout mettre en critical — le téléphone vibrait des dizaines de fois par jour, j’ai fini par ignorer les alertes. Quand le vrai problème est arrivé, plus de réaction.
Stratégie de niveaux d’alerte
Trois niveaux, affinés après plusieurs incidents :
| Niveau | Conditions | Action requise |
|---|---|---|
| Critical | Service down, GPU >95 %, taux d’erreur >20 % | Immédiat (Slack + push mobile) |
| Warning | Latence >60 s, GPU >80 %, taux d’erreur >5 % | Sous 1 h (Slack uniquement) |
| Info | Changement de modèle, nouveau déploiement | Journalisation (récap email) |
Principe clé : peu d’alertes Critical — chacune doit alerter vraiment.
Règles d’alerte Prometheus
Dans prometheus.yml, ajoutez :
rule_files:
- 'ollama_alerts.yml'
Fichier ollama_alerts.yml :
# ollama_alerts.yml
groups:
- name: ollama_critical
rules:
# Alerte service down
- alert: OllamaServiceDown
expr: up{job="ollama-exporter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service Ollama indisponible"
description: "Impossible de joindre l'exporter Ollama, le service est peut-être arrêté"
# Alerte mémoire GPU (>95 %)
- alert: GPUMemoryCritical
expr: nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes > 0.95
for: 2m
labels:
severity: critical
annotations:
summary: "Mémoire GPU presque épuisée"
description: "GPU {{ gpu_id }} : utilisation mémoire >95 %, actuellement {{ $value | humanizePercentage }}"
# Alerte taux d'erreur élevé
- alert: HighErrorRate
expr: rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) > 0.20
for: 3m
labels:
severity: critical
annotations:
summary: "Taux d'erreur des requêtes trop élevé"
description: "Taux d'erreur >20 % sur les 5 dernières minutes, vérifiez les logs"
- name: ollama_warning
rules:
# Alerte temps de réponse
- alert: SlowResponseTime
expr: histogram_quantile(0.95, rate(ollama_request_duration_seconds_bucket[5m])) > 60
for: 5m
labels:
severity: warning
annotations:
summary: "Latence P95 trop élevée"
description: "95 % des requêtes dépassent 60 secondes"
# Avertissement mémoire GPU
- alert: GPUMemoryWarning
expr: nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes > 0.80
for: 5m
labels:
severity: warning
annotations:
summary: "Utilisation mémoire GPU élevée"
description: "GPU {{ gpu_id }} : utilisation mémoire >80 %"
# Avertissement taux d'erreur
- alert: ErrorRateWarning
expr: rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "Taux d'erreur en hausse"
description: "Taux d'erreur >5 % sur les 5 dernières minutes"
Points importants :
for: Xm: déclenchement après X minutes continues, évite les faux positifs sur pics instantanés- Seuil GPU 95 % : au-delà, les problèmes arrivent quasi immédiatement en pratique
rate()pour le taux d’erreur : les valeurs absolues ne suffisent pas, il faut la tendance
Configuration AlertManager
AlertManager envoie les alertes. Fichier alertmanager.yml :
global:
resolve_timeout: 5m
# Routage
route:
group_by: ['severity', 'alertname']
group_wait: 30s # attendre 30 s pour regrouper
group_interval: 5m # intervalle entre alertes du même groupe
repeat_interval: 3h # répétition si non résolu
routes:
- match:
severity: critical
receiver: 'critical-alerts'
continue: false
- match:
severity: warning
receiver: 'warning-alerts'
continue: false
- match:
severity: info
receiver: 'info-alerts'
# Récepteurs
receivers:
- name: 'critical-alerts'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ollama-critical'
send_resolved: true
title: '{{ .Status | toUpper }}: {{ .CommonAnnotations.summary }}'
text: '{{ .CommonAnnotations.description }}'
- name: 'warning-alerts'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ollama-monitor'
send_resolved: true
- name: 'info-alerts'
email_configs:
- to: '[email protected]'
send_resolved: true
Configuration Slack Webhook
- Créer une App Slack (ou Incoming Webhooks)
- Ajouter l’URL Webhook dans
api_url - Canaux séparés : critical dédié, warning général
J’ajoute aussi une notification mobile. PagerDuty et OpsGenie s’intègrent à AlertManager. Gratuitement, un bot Telegram fonctionne aussi.
Silences et règles d’inhibition
Parfois il faut couper les alertes temporairement — maintenance par exemple. Dans l’UI AlertManager :
# Accéder à l'UI AlertManager
http://your-server:9093
# Silences -> New Silence
# Définir durée et labels correspondants
Ou via API :
curl -X POST http://localhost:9093/api/v1/silences \
-d '{
"matchers": [{"name": "alertname", "value": "OllamaServiceDown", "isRegex": false}],
"startsAt": "2026-04-12T10:00:00Z",
"endsAt": "2026-04-12T12:00:00Z",
"createdBy": "admin",
"comment": "Scheduled maintenance"
}'
Outils de surveillance LLM avancés
Prometheus + Grafana couvre l’infrastructure, mais les LLM ont des besoins spécifiques : traçage des prompts, coût en tokens, évaluation de la qualité. Difficile avec les outils classiques.
Langfuse : traçage LLM et gestion des prompts
Langfuse est une plateforme de surveillance dédiée aux applications LLM, open source MIT, auto-hébergeable. Fonctionnalités :
- Tracer chaque conversation : prompt d’entrée, réponse, tokens, durée
- Gestion des versions de prompts : comparer l’effet des modifications
- Évaluation qualité : feedback utilisateur, annotation manuelle, suivi de la qualité
L’intégration est simple — Langfuse propose un adaptateur Ollama :
# Exemple d'intégration Python
from langfuse import Langfuse
import requests
langfuse = Langfuse(
public_key="pk-xxx",
secret_key="sk-xxx",
host="https://cloud.langfuse.com" # ou adresse auto-hébergée
)
# Enregistrer chaque appel
trace = langfuse.trace(
name="ollama-chat",
input={"prompt": user_prompt},
metadata={"model": "llama3.1"}
)
response = requests.post(
"http://localhost:11434/api/generate",
json={"model": "llama3.1", "prompt": user_prompt}
)
trace.update(
output=response.json()["response"],
metadata={"tokens": response.json().get("eval_count", 0)}
)
Déploiement auto-hébergé avec Docker :
services:
langfuse-server:
image: langfuse/langfuse:latest
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/langfuse
- NEXTAUTH_SECRET=your-secret
Avec LangChain, l’intégration est encore plus simple via le callback handler officiel.
SigNoz : surveillance unifiée OpenTelemetry
SigNoz est une plateforme d’observabilité basée sur OpenTelemetry — logs, métriques et traces en un seul endroit. Plus besoin de maintenir Prometheus, Jaeger et ELK séparément.
Pour les applications LLM, le traçage SigNoz montre la chaîne complète : entrée API → inférence modèle → requête base de données.
Le déploiement demande des ressources — minimum 4 Go RAM. Docker Compose officiel en une commande :
git clone https://github.com/SigNoz/signoz.git
cd signoz/deploy/docker
docker compose up -d
Recommandations de choix d’outils
Selon le contexte :
| Scénario | Solution recommandée | Raison |
|---|---|---|
| Petite équipe (<5 personnes) | Prometheus + Grafana | Simple, communauté riche |
| Traçage de prompts requis | Prometheus + Langfuse | Langfuse pour la couche LLM, complémentaire |
| Entreprise multi-services | SigNoz + OpenTelemetry | Plateforme unifiée, coût ops réduit |
| Cloud natif pur | Service managé | Moins d’effort ops |
Mon setup actuel : Prometheus + Grafana + Langfuse. Prometheus pour l’infrastructure, Langfuse pour la couche application LLM — responsabilités claires.
Pour conclure
En résumé : n’attendez pas la panne pour penser à la surveillance.
Mon alerte à trois heures du matin m’a conduit à cette solution complète. Mon service Ollama tourne depuis plus d’un an ; quelques alertes mémoire GPU, toutes traitées au niveau Warning — plus de réveil nocturne.
Le coût de mise en place reste modeste. J’ai regroupé tous les fichiers de config :
- Configuration service systemd
- Docker Compose complet (Ollama + Exporter + Prometheus + Grafana)
- Règles d’alerte Prometheus
- Modèle AlertManager
- JSON dashboard Grafana
Le dépôt GitHub est en bas de l’article. Configuré, comptez 20 minutes si vous êtes à l’aise, une demi-heure pour débuter.
Prochaines étapes :
- Démarrer avec Prometheus + Grafana pour les métriques de base
- Observer 3 à 5 jours pour connaître les plages normales
- Ajuster les seuils d’alerte selon la réalité
- Ajouter Langfuse si vous devez tracer les prompts
La surveillance, c’est un investissement unique à retour continu. J’espère que vous n’aurez pas besoin d’une alerte à trois heures du matin pour l’apprendre.
Dépôt de configuration : github.com/yourname/ollama-monitoring-config (lien exemple — remplacez en déploiement réel)
Articles de la série :
- Guide complet de déploiement local Ollama — premier article de la série
- Optimisation des performances Ollama — prochain article
FAQ
Quelles métriques essentielles surveiller pour Ollama en production ?
Quelle différence entre Prometheus + Grafana et Langfuse ?
Comment définir des seuils d'alerte raisonnables ?
Comment éviter la croissance illimitée des logs en déploiement Docker ?
Comment surveiller chaque carte GPU séparément ?
Comment diagnostiquer rapidement une alerte à 3 h du matin ?
12 min de lecture · Publié le: 12 avr. 2026 · Mis à jour le: 27 juil. 2026
Guide Ollama LLM local
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Quantification de modèles Ollama : format GGUF et perte de précision expliqués
Principes de la quantification GGUF dans Ollama, données Red Hat sur 500K+ évaluations pour mesurer la perte de précision, et recommandations par configuration matérielle pour exécuter de grands modèles sur GPU grand public.
Partie 16 sur 18
Suivant
Mnemo avec Ollama : mémoire locale et déploiement
Mnemo donne à Ollama une mémoire intersession avec Rust, SQLite et un graphe. Testez son API puis évaluez suppression, migration et partage entre agents.
Partie 18 sur 18



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire