1. Le modèle des métriques #
MeterProvider, meters, instruments.
De la mesure au point exporté #
Le code enregistre des mesures sur des instruments créés par un meter. Le SDK les agrège (somme, histogramme, dernière valeur) par combinaison d'attributs, puis un metric reader les exporte périodiquement (60 s par défaut, OTEL_METRIC_EXPORT_INTERVAL).
from opentelemetry import metrics
meter = metrics.get_meter("shop.checkout", "1.4.0")
commandes = meter.create_counter("shop.orders", unit="{order}", description="Commandes validées")
duree = meter.create_histogram("http.server.request.duration", unit="s")
commandes.add(1, {"shop.payment.method": "card"})
duree.record(0.183, {"http.request.method": "POST", "http.route": "/orders", "http.response.status_code": 201})Les instruments #
| Instrument | Synchrone | Asynchrone (observable) | Agrégation par défaut |
|---|---|---|---|
| Counter | add() dans le code | ObservableCounter (lire un total existant) | somme monotone |
| UpDownCounter | add(+1/-1) | ObservableUpDownCounter | somme non monotone |
| Histogram | record() | — | histogramme |
| Gauge | set() | ObservableGauge (callback à chaque export) | dernière valeur |
2. Temporalité et histogrammes #
Deux notions qui surprennent.
Cumulative ou delta #
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative # ou delta, lowmemoryÀ savoir : Le processeur deltatocumulative du Collector convertit le delta en cumulatif avant un envoi vers Prometheus.Histogrammes #
| Type | Principe | Atout |
|---|---|---|
| Explicite | bornes fixées (par défaut 0, 5, 10, 25… 10000) | compatible partout |
| Exponentiel | bornes calculées automatiquement à partir d'une échelle | précis sur toute la plage sans réglage ; correspond aux histogrammes natifs Prometheus |
Erreur Courante : Les bornes par défaut sont en millisecondes « historiques » : pour une durée en secondes (unit="s"), définissez des bornes adaptées par une vue (0.005, 0.01, 0.025… 10) ou utilisez l'histogramme exponentiel.3. Vues et cardinalité #
Contrôler ce qui est produit.
Les vues #
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.view import View, ExplicitBucketHistogramAggregation, DropAggregation
provider = MeterProvider(metric_readers=[reader], views=[
View(instrument_name="http.server.request.duration",
aggregation=ExplicitBucketHistogramAggregation([0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5])),
View(instrument_name="http.server.request.duration", attribute_keys={"http.request.method", "http.route", "http.response.status_code"}),
View(instrument_name="db.client.connection.*", aggregation=DropAggregation()), # supprimer des métriques inutiles
])Cardinalité #
Chaque combinaison distincte d'attributs crée une série. 5 méthodes × 50 routes × 10 codes = 2 500 séries par instance. Un attribut user.id multiplie ce nombre par le nombre d'utilisateurs : le backend sature et la facture explose.
Bonne Pratique : Sur les métriques, n'utilisez que des attributs bornés (route, méthode, code, région). Les identifiants vont sur les spans et les logs.
4. Exemplars et Prometheus #
Relier une métrique à une trace.
Exemplars #
Un exemplar est un point de mesure particulier conservé avec son trace_id : sur un pic de latence p99, on clique sur l'exemplar et on ouvre la trace exacte d'une requête lente. Le filtre OTEL_METRICS_EXEMPLAR_FILTER=trace_based (défaut) n'enregistre que les mesures faites dans un span échantillonné.
Vers Prometheus #
| OpenTelemetry | Prometheus |
|---|---|
shop.orders (Counter, unit {order}) | shop_orders_total |
http.server.request.duration (Histogram, unit s) | http_server_request_duration_seconds_bucket, _sum, _count |
attribut http.route | label http_route |
ressource service.name | labels job / instance et métrique target_info |
# Prometheus 3 accepte l'OTLP nativement
prometheus --web.enable-otlp-receiver # point d'entrée : /api/v1/otlp/v1/metrics
# ou dans le Collector : exportateur prometheusremotewrite, ou prometheus (scrape)Mon suivi
Connectez-vous pour suivre votre progression et prendre des notes. Se connecter
Articles recommandés
Architecture distribuée Elasticsearch : rôles des nœuds, shards, répliques et allocation
Comprendre le fonctionnement distribué d'Elasticsearch : rôles des nœuds, nœuds master et quorum,...
Mappings et analyse de texte Elasticsearch : types de champs, analyseurs et mapping dynamique
Maîtriser les mappings Elasticsearch : types de champs (text, keyword, numériques, date, ip, nest...
Ingestion Elasticsearch : Bulk API, ingest pipelines, enrich et reindex
Ingérer et transformer des données dans Elasticsearch : Bulk API, ingest pipelines et processeurs...
Index Lifecycle Management (ILM) : data tiers, rollover et rétention
Automatiser le cycle de vie des index avec ILM : data tiers hot, warm, cold et frozen, rollover p...
Data streams et templates Elasticsearch : component templates, index templates et séries temporelles
Gérer les données horodatées avec les data streams : index templates et component templates, conv...
Query DSL et agrégations avancées Elasticsearch, avec ES|QL
Écrire des requêtes Elasticsearch avancées : bool, filter et score, nested, function_score et per...
Monitoring et troubleshooting Elasticsearch : santé, shards non assignés, JVM, hot threads et slow logs
Diagnostiquer un cluster Elasticsearch : cluster health et CAT APIs, shards non assignés et alloc...
Performance et capacity planning Elasticsearch : shards, heap, indexation et benchmarks
Dimensionner et optimiser Elasticsearch : taille et nombre de shards, heap JVM, caches, réglages ...
Snapshot Lifecycle Management : sauvegardes automatisées, restauration et reprise après sinistre
Protéger les données Elasticsearch : dépôts de snapshots (S3, GCS, Azure, système de fichiers), p...