📍 Article principal : Observabilité applicative en 2026 : OpenTelemetry, traces distribuées et stack LGTM — pour le contexte conceptuel et l’architecture d’ensemble.
Pourquoi envoyer les métriques vers Mimir
Mimir est le stockage de métriques scalable de la stack Grafana, compatible Prometheus en lecture (PromQL) et accepté par les outils de l’écosystème en écriture (remote_write Prometheus, OTLP). Sa particularité par rapport à un Prometheus mono-instance est l’horizontalité : on peut stocker des dizaines de millions de séries actives sur stockage objet sans toucher aux limites mémoire d’un nœud unique. La version 3 sortie en 2026 a renforcé fiabilité et performance, ce qui en fait une alternative crédible à Prometheus dès que la cardinalité ou la rétention deviennent problématiques.
Côté ingestion, Mimir accepte deux entrées principales : le format Prometheus remote_write historique (utilisé par Prometheus, Grafana Agent, l’agent OTel via un exporter dédié) et le format OTLP HTTP qui ingère directement les métriques OTel sans conversion intermédiaire. Ce tutoriel construit la pipeline OTLP → Mimir et explique les choix de configuration côté Collector et côté Mimir.
Prérequis
- Une instance Mimir 2.13+ joignable (Docker, binaire ou Kubernetes)
- Un OpenTelemetry Collector configuré — voir le tutoriel Configurer un OpenTelemetry Collector
- Une application instrumentée qui produit des métriques OTLP
- Une instance Grafana pour la visualisation
- Connaissance de base de PromQL
- Temps estimé : 30 à 45 minutes
Étape 1 — Vérifier l’endpoint OTLP de Mimir
Mimir expose deux endpoints d’ingestion : /api/v1/push pour le format Prometheus remote_write, et /otlp/v1/metrics pour OTLP HTTP. La voie OTLP est plus directe quand l’origine des métriques est un SDK OTel.
curl http://127.0.0.1:9009/ready
curl http://127.0.0.1:9009/api/v1/status/buildinfo
Si /ready répond, Mimir est prêt. Le port 9009 est l’API HTTP par défaut en mode monolithique. Pour un déploiement microservices Mimir, le port et le service à cibler dépendent du composant — ici l’distributor est l’entrée. La doc Grafana Mimir détaille la cartographie selon le profil de déploiement.
Étape 2 — Configurer Mimir pour accepter OTLP
Le distributor de Mimir accepte OTLP par défaut depuis les versions 2.13+. Aucune configuration spécifique n’est nécessaire pour activer le receiver — il suffit de pointer vers /otlp/v1/metrics. En revanche, certaines règles de conversion entre attributs OTLP et labels Prometheus sont configurables.
# mimir.yaml (extrait)
limits:
otel_metric_suffixes_enabled: true
otel_created_timestamp_zero_ingestion_enabled: true
promote_otel_resource_attributes:
- service.name
- service.namespace
- service.instance.id
- deployment.environment
- cluster
- k8s.cluster.name
L’option otel_metric_suffixes_enabled ajoute les suffixes _total, _seconds, _bytes selon les conventions Prometheus, ce qui rend les noms cohérents avec ce qu’attend PromQL. promote_otel_resource_attributes élève les attributs de resource OTel au rang de labels Prometheus, ce qui permet de filtrer par service ou environnement comme on le ferait sur du Prometheus natif.
Étape 3 — Configurer l’exporter Mimir côté Collector
Côté Collector, on utilise l’exporter otlphttp standard. La cible est /otlp — le suffixe /v1/metrics est ajouté automatiquement par l’exporter. L’en-tête X-Scope-OrgID identifie le tenant pour Mimir multi-tenants ; en mode mono-tenant ou en dev, la valeur anonymous convient.
# otelcol.yaml (extension)
exporters:
otlphttp/mimir:
endpoint: http://mimir:9009/otlp
headers:
X-Scope-OrgID: anonymous
sending_queue:
enabled: true
num_consumers: 4
queue_size: 5000
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
service:
pipelines:
metrics:
receivers: [otlp]
processors: [memory_limiter, resource, batch]
exporters: [otlphttp/mimir]
La queue d’envoi et le retry suivent la même logique que pour Tempo et Loki : indispensables en production. Sans eux, une coupure réseau de 30 secondes peut faire perdre la fenêtre de métriques correspondante. À noter que les métriques sont moins critiques à perdre que les traces ou les logs (on récupérera les valeurs au prochain cycle), mais la résilience reste préférable.
Étape 4 — Vérifier l’arrivée des métriques
On déclenche du trafic depuis l’application instrumentée et on consulte Mimir via PromQL. La voie la plus directe est l’API /prometheus/api/v1/query qui parle PromQL standard.
# vérifier qu'au moins une série est arrivée
curl -G "http://127.0.0.1:9009/prometheus/api/v1/query" \
-H "X-Scope-OrgID: anonymous" \
--data-urlencode 'query=app_score_computed_total' | jq
# top 10 services par taux de spans
curl -G "http://127.0.0.1:9009/prometheus/api/v1/query" \
-H "X-Scope-OrgID: anonymous" \
--data-urlencode 'query=topk(10, rate(http_server_request_duration_seconds_count[5m]))' | jq
Si la réponse contient un tableau result non vide avec les valeurs récentes, l’ingestion fonctionne. Si elle est vide, vérifier dans cet ordre : que l’application a bien émis depuis quelques minutes, que le Collector logue des batchs métriques, et que l’en-tête X-Scope-OrgID est cohérent entre l’envoi et la lecture.
Étape 5 — Comprendre la conversion OTel vers Prometheus
Les conventions sémantiques OTel utilisent des points dans les noms d’attributs et des unités explicites dans les noms de métriques. Mimir applique des règles de conversion bien documentées :
- Les points dans les noms d’attributs deviennent des underscores (
service.name→service_name) - Le nom de la métrique prend un suffixe Prometheus : Counter →
_total, Histogram avec buckets →_bucket,_sum,_count - Les unités sont incluses dans le nom si
otel_metric_suffixes_enabledest actif (app.durationen secondes →app_duration_seconds) - Les attributs de resource promus deviennent des labels Prometheus globaux à toutes les séries du service
Une métrique OTel app.score.computed de type Counter avec attribut de resource service.name=otel-go-demo apparaît côté Mimir comme app_score_computed_total{service_name="otel-go-demo"}. Cette régularité rend les requêtes prévisibles et cohérentes entre Prometheus natif et OTel.
Étape 6 — Premiers PromQL utiles
PromQL est le langage de requête de Prometheus, repris à l’identique par Mimir. Sa puissance vient des fonctions de range (rate, increase, histogram_quantile) qui transforment les contre-tendances en grandeurs interprétables.
# taux de requêtes HTTP par service sur 5 minutes
sum by (service_name) (
rate(http_server_request_duration_seconds_count[5m])
)
# latence p99 par route
histogram_quantile(0.99,
sum by (le, http_route) (
rate(http_server_request_duration_seconds_bucket[5m])
)
)
# taux d'erreur HTTP 5xx par service
sum by (service_name) (
rate(http_server_request_duration_seconds_count{http_response_status_code=~"5.."}[5m])
)
/
sum by (service_name) (
rate(http_server_request_duration_seconds_count[5m])
)
Ces trois requêtes constituent le socle des dashboards SRE classiques (Rate, Errors, Duration). Combinées, elles produisent une vue à un coup d’œil de la santé de chaque service, sans investigation approfondie nécessaire pour repérer une anomalie.
Étape 7 — Configurer le datasource Mimir dans Grafana
Côté Grafana, on configure un datasource Prometheus standard, en pointant vers l’endpoint /prometheus de Mimir et en passant l’en-tête tenant.
# grafana datasource — provisioning
apiVersion: 1
datasources:
- name: Mimir
type: prometheus
uid: mimir
url: http://mimir:9009/prometheus
jsonData:
httpHeaderName1: X-Scope-OrgID
exemplarTraceIdDestinations:
- name: trace_id
datasourceUid: tempo
secureJsonData:
httpHeaderValue1: anonymous
L’option exemplarTraceIdDestinations active une corrélation puissante : sur un graphique de latence p99 dans Grafana, chaque point d’histogramme peut afficher un exemple de trace correspondant. Cliquer sur l’exemplar ouvre la trace correspondante dans Tempo. Cette mécanique permet de partir d’une métrique anormale et d’arriver en une étape sur un cas concret de la pathologie.
Étape 8 — Alertes via les recording rules
Mimir supporte les recording rules et alerting rules au format Prometheus standard. On les définit dans un fichier YAML et on les charge via l’API de Mimir. C’est le mécanisme typique pour pré-calculer des métriques agrégées à intervalles réguliers et déclencher des alertes.
# rules.yaml
groups:
- name: http-rules
interval: 30s
rules:
- record: http:request_rate:5m
expr: sum by (service_name) (rate(http_server_request_duration_seconds_count[5m]))
- record: http:p99_latency:5m
expr: histogram_quantile(0.99, sum by (le, service_name) (rate(http_server_request_duration_seconds_bucket[5m])))
- alert: HighErrorRate
expr: |
sum by (service_name) (rate(http_server_request_duration_seconds_count{http_response_status_code=~"5.."}[5m]))
/ sum by (service_name) (rate(http_server_request_duration_seconds_count[5m])) > 0.05
for: 10m
labels:
severity: warning
annotations:
summary: "Error rate {{ $value | humanizePercentage }} on {{ $labels.service_name }}"
Les recording rules pré-calculent http:request_rate:5m toutes les 30 secondes, ce qui rend les dashboards plus rapides en évitant de recomputer le rate à chaque ouverture. L’alerting rule HighErrorRate se déclenche si le taux d’erreur 5xx dépasse 5 % pendant 10 minutes.
Erreurs fréquentes
Cardinalité explosive due à des labels mal choisis
L’erreur la plus dommageable. Mettre user.id ou request.id en attribut de métrique génère une nouvelle série temporelle par valeur unique. À mille utilisateurs actifs par minute, on crée mille séries en cinq minutes. Mimir tient mieux que Prometheus mono-instance, mais ce n’est pas une excuse pour faire n’importe quoi : les attributs de métrique doivent rester énumérables.
Confondre /otlp et /otlp/v1/metrics côté Collector
L’exporter otlphttp ajoute lui-même /v1/metrics. Pointer vers /otlp/v1/metrics produit un 404. La cible doit être /otlp tout court.
Oublier le tenant ID en multi-tenants
Sans X-Scope-OrgID, l’ingestion échoue silencieusement avec un 401 ou un 403 selon la configuration. Vérifier la cohérence entre l’écriture (Collector) et la lecture (Grafana) — un tenant en écriture mais un autre en lecture donne des dashboards vides sans erreur visible.
Backend de stockage local en production
Comme Tempo et Loki, Mimir supporte un backend local qui n’est pas adapté à la production. Toujours utiliser S3, GCS ou Azure Blob avec une rétention adaptée — typiquement 13 mois pour conserver le year-over-year sans exploser les coûts.
Mélanger remote_write Prometheus et OTLP sans précaution
Si une partie des services pousse en remote_write Prometheus et l’autre en OTLP, les noms de métriques peuvent diverger légèrement (suffixes, formats d’attribut). Standardiser le pipeline ou aligner les conventions de nommage évite des PromQL en double pour exprimer la même chose.
Tutoriels associés
- Configurer un OpenTelemetry Collector
- Envoyer les traces vers Tempo
- Corréler trace_id entre logs, métriques et traces dans Grafana
- 🔝 Retour à l’article principal — Observabilité applicative et stack LGTM
Ressources et références officielles
- Mimir documentation : grafana.com/docs/mimir/latest
- Configuration Mimir : grafana.com/docs/mimir/latest/configure
- OTLP ingestion Mimir : grafana.com/docs/mimir/latest/send/native-otlp
- PromQL — référence : prometheus.io/docs/prometheus/latest/querying/basics
- Conventions sémantiques OTel — métriques : opentelemetry.io/docs/specs/semconv/general/metrics
- Recording et alerting rules : prometheus.io/docs/prometheus/latest/configuration/recording_rules
FAQ
Mimir remplace-t-il Prometheus ?
Pour la durabilité et la scalabilité, oui souvent. Pour le scrape local, beaucoup d’équipes gardent un Prometheus mono-instance qui scrape, puis remote_write vers Mimir. Cette topologie tire le meilleur des deux : autonomie du scrape, durabilité du stockage.
Mimir vs VictoriaMetrics ?
VictoriaMetrics est plus dense (souvent 50-70 % moins de stockage à cardinalité égale) et plus rapide en query. Mimir s’intègre nativement à Grafana et Tempo, avec des fonctionnalités multi-tenants matures. Le choix dépend des contraintes : VictoriaMetrics pour la performance brute, Mimir pour l’intégration LGTM.
Faut-il OTLP ou remote_write Prometheus ?
OTLP si l’origine est un SDK OTel — pas de conversion intermédiaire. remote_write si l’origine est un Prometheus existant ou un Grafana Agent. Les deux coexistent dans Mimir sans problème.
Comment limiter la cardinalité ?
Mimir supporte des limites de cardinalité par tenant et alerte quand elles sont dépassées. Côté Collector, le processor filter permet de retirer des métriques ou des labels indésirables avant ingestion. La meilleure ligne de défense reste l’hygiène d’instrumentation côté SDK : ne jamais mettre des identifiants en attributs de métrique.
Quelle rétention typique pour les métriques ?
13 mois est une cible commune (year-over-year). Pour des analyses plus longues, on agrège les métriques fines en métriques pré-calculées via recording rules avec un downsampling adapté (5 min sur 1 an, 1h sur 5 ans).