Comment interroger Prometheus sur Ubuntu 14.04 Partie 2

Un article de Prometheus, ​​co-créateur Julius Volz

introduction

Prometheus est un système de surveillance open source et une base de données de séries chronologiques. Dans le lien: / community / tutorials / procédure d’interrogation-prometheus-on-ubuntu-14-04-part-1 [Procédure d’interrogation de Prometheus sur Ubuntu 14.04 Partie 1], nous avons configuré trois instances de service de démonstration exposant des métriques synthétiques à un serveur Prometheus. À l’aide de ces métriques, nous avons ensuite appris à utiliser le langage de requête Prometheus pour sélectionner et filtrer les séries chronologiques, à agréger des dimensions, ainsi qu’à calculer des taux et des dérivés.

Dans la deuxième partie de ce didacticiel, nous allons nous appuyer sur la configuration de la première partie pour apprendre des techniques et des modèles d’interrogation plus avancés. Après ce didacticiel, vous saurez comment appliquer le filtrage basé sur les valeurs, les opérations définies, les histogrammes, etc.

Conditions préalables

Ce tutoriel est basé sur la configuration décrite dans le lien: / community / tutorials / procédure d’interrogation de Prometheus sur Ubuntu 14-04-part-1 [Comment interroger Prometheus sur Ubuntu 14.04 Partie 1]. Au minimum, vous devrez suivre les étapes 1 et 2 de ce tutoriel pour configurer un serveur Prometheus et trois instances de service de démonstration surveillées. Cependant, nous nous appuierons également sur les techniques du langage de requête expliquées dans la première partie et nous vous recommandons donc de les utiliser entièrement.

Étape 1 - Filtrage par valeur et utilisation de seuils

Dans cette section, nous allons apprendre à filtrer les séries temporelles renvoyées en fonction de leur valeur.

L’utilisation la plus courante du filtrage basé sur la valeur concerne les seuils d’alerte numériques simples. Par exemple, nous voudrons peut-être rechercher des chemins HTTP dont le taux de requêtes total supérieur à + 500 + est supérieur à 0,2 par seconde, en moyenne sur les 15 dernières minutes. Pour ce faire, nous interrogeons simplement tous les débits de requête `+ 500 + -status, puis ajoutons un opérateur de filtre +> 0.2 + à la fin de l’expression:

rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[15m]) > 0.2

Dans la vue * Console *, le résultat devrait ressembler à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/filter_rates_scalar.png [Taux de demande de filtrage par numéro scalaire]

Toutefois, comme pour l’arithmétique binaire, Prométhée ne prend pas en charge le filtrage par un seul nombre scalaire. Vous pouvez également filtrer un ensemble de séries temporelles basé sur un autre ensemble de séries. De nouveau, les éléments sont appariés par leurs jeux d’étiquettes et l’opérateur de filtrage est appliqué entre les éléments correspondants. Seuls les éléments du côté gauche qui correspondent à un élément du côté droit et qui passent le filtre deviennent partie intégrante de la sortie. Les clauses + sur (<labels>) +, + group_left (<labels>) +, + group_right (<labels>) + fonctionnent de la même manière que dans les opérateurs arithmétiques.

Par exemple, nous pourrions sélectionner le taux de statuts "+ 500 " pour toutes les combinaisons ` job `, ` instance `, ` méthode ` et ` chemin ` pour lesquelles le taux de statuts ` 200 +` est pas au moins 50 fois plus élevé que le taux 500 +

   rate(demo_api_request_duration_seconds_count{status="500",job="demo"}[5m]) * 50
> on(job, instance, method, path)
   rate(demo_api_request_duration_seconds_count{status="200",job="demo"}[5m])

Cela ressemblera à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/series.png [Filtrage des taux de demandes par d’autres séries de séries]

Outre +> +, Prometheus prend également en charge les opérateurs de comparaison habituels +> = +, + ⇐ +, + <+, +! = + Et `+ == + ' dans le filtrage.

Nous savons maintenant comment filtrer un ensemble de séries chronologiques, en fonction d’une seule valeur numérique ou d’un autre ensemble de valeurs de séries chronologiques avec des étiquettes correspondantes.

Étape 2 - Utilisation des opérateurs de sets

Dans cette section, vous apprendrez à utiliser les opérateurs d’ensembles de Prometheus pour mettre en corrélation des ensembles de séries temporelles.

Souvent, vous souhaitez filtrer un ensemble de séries temporelles basé sur un autre ensemble. Pour cela, Prométhée fournit les opérateurs + et +. Pour chaque série du côté gauche de l’opérateur, il essaie de trouver une série du côté droit avec les mêmes étiquettes. Si une correspondance est trouvée, la série du côté gauche devient partie intégrante de la sortie. Si aucune série correspondante n’existe à droite, la série est omise de la sortie.

Par exemple, vous pouvez sélectionner des points d’extrémité HTTP dont la latence au 90e percentile est supérieure à 50 ms (0,05 s), mais uniquement pour les combinaisons dimensionnelles recevant plus d’une demande par seconde. Nous allons utiliser la fonction + histogram_quantile () + pour le calcul du centile ici. Nous expliquerons dans la section suivante que cette fonction fonctionne exactement. Pour l’instant, le fait qu’il calcule la latence au 90e percentile pour chaque sous-dimension importe uniquement. Pour filtrer les mauvaises latences résultantes et ne conserver que celles qui reçoivent plus d’une demande par seconde, nous pouvons interroger:

   histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])) > 0.05
and
   rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 1

image: https: //assets.digitalocean.com/articles/prometheus_querying/intersection.png [Filtrage des taux de demande par intersection]

Au lieu de prendre l’intersection, vous souhaitez parfois créer l’union à partir de deux séries chronologiques. Prometheus fournit l’opérateur set + ou + pour cela. Il en résulte la série du côté gauche de l’opération, ainsi que toute série du côté droit qui n’a pas d’ensembles d’étiquettes identiques à gauche. Par exemple, pour répertorier tous les taux de demande inférieurs à 10 ou supérieurs à 30, interrogez:

   rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) < 10
or
   rate(demo_api_request_duration_seconds_count{job="demo"}[5m]) > 30

Le résultat ressemblera à ceci dans un graphique:

image: https: //assets.digitalocean.com/articles/prometheus_querying/union.png [Création de l’union à partir de deux ensembles de taux de demande]

Comme vous pouvez le constater, l’utilisation de filtres de valeur et d’opérations définies dans les graphiques peut entraîner l’apparition et la disparition de séries chronologiques dans le même graphique, selon qu’elles correspondent ou non à un filtre à un pas quelconque du graphique. En règle générale, l’utilisation de ce type de logique de filtrage est recommandée uniquement pour les règles d’alerte.

Vous savez maintenant comment construire des intersections et des unions à partir de séries chronologiques étiquetées.

Étape 3 - Travailler avec des histogrammes

Dans cette section, nous allons apprendre à interpréter les métriques d’histogramme et à en calculer les quantiles (une forme généralisée de centiles).

Prometheus prend en charge les métriques d’histogramme, qui permettent à un service d’enregistrer la distribution d’une série de valeurs. Les histogrammes suivent généralement des mesures telles que les latences des demandes ou la taille des réponses, mais peuvent suivre essentiellement toute valeur dont l’amplitude fluctue en fonction d’une distribution donnée. Les histogrammes Prometheus sample du côté client, ce qui signifie qu’ils comptent les valeurs observées à l’aide d’un certain nombre de paramètres configurables (par exemple, latence) et les exposer ensuite sous forme de séries chronologiques individuelles.

En interne, les histogrammes sont implémentés en tant que groupe de séries chronologiques qui représentent chacune le nombre pour un compartiment donné (par ex. "Demandes sous 10 ms", "demandes sous 25 ms", "demandes sous 50 ms", etc.). Les compteurs de compartiment sont cumulatifs, ce qui signifie que les compartiments pour les valeurs plus grandes incluent les comptes de tous les compartiments de valeur inférieure. Sur chaque série temporelle faisant partie d’un histogramme, le segment correspondant est indiqué par l’étiquette spéciale + le + (inférieur ou égal). Cela ajoute une dimension supplémentaire à toutes les dimensions existantes que vous suivez déjà.

Par exemple, notre service de démonstration exporte un histogramme + demo_api_request_duration_seconds_bucket + qui suit la distribution des durées des demandes d’API. Comme cet histogramme exporte 26 compartiments par sous-dimension suivie, cette métrique contient de nombreuses séries chronologiques. Examinons d’abord l’histogramme brut pour un type de demande, par exemple:

demo_api_request_duration_seconds_bucket{instance="localhost:8080",method="POST",path="/api/bar",status="200",job="demo"}

Vous devriez voir 26 séries représentant chacune un seau d’observation, identifié par l’étiquette + le +:

image: https: //assets.digitalocean.com/articles/prometheus_querying/histogram.png [Série d’histogrammes bruts]

Un histogramme peut vous aider à répondre à des questions telles que «Combien de mes demandes prennent plus de 100 ms?» (À condition que l’histogramme ait un compartiment configuré avec une limite de 100 ms). D’autre part, vous souhaitez souvent répondre à une question connexe telle que «Quelle est la latence à laquelle 99% de mes requêtes se terminent?». Si les compartiments de votre histogramme sont suffisamment fins, vous pouvez le calculer à l’aide de la fonction + histogram_quantile () +. Cette fonction attend une métrique d’histogramme (un groupe de séries avec les étiquettes de compartiment + le +) en entrée et génère les quantiles correspondants. Contrairement aux centiles, qui vont du 0e au 100e centiles, la spécification de quantile cible attendue par la fonction + histogram_quantile () + est comprise entre + 0 + et + 1 + (la 90e le centile correspondrait à un quantile de «+ 0.9 +».

Par exemple, nous pourrions essayer de calculer la latence de l’API au 90e percentile sur tous les temps pour toutes les dimensions, comme ceci:

# BAD!
histogram_quantile(0.9, demo_api_request_duration_seconds_bucket{job="demo"})

Ce n’est pas très utile ou fiable. Les compteurs de compartiment sont réinitialisés lorsque des instances de service individuelles sont redémarrées et vous souhaitez généralement connaître la latence «maintenant» (par exemple, mesurée au cours des 5 dernières minutes), plutôt que pendant toute la durée de la métrique. Vous pouvez y parvenir en appliquant une fonction + rate () + aux compteurs de compartiment de l’histogramme sous-jacent, qui traite à la fois des réinitialisations de compteur et considère uniquement le taux d’augmentation de chaque compartiment au cours de la fenêtre temporelle spécifiée.

Calculez la latence de l’API du 90e percentile au cours des 5 dernières minutes comme suit:

# GOOD!
histogram_quantile(0.9, rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m]))

C’est beaucoup mieux et ressemblera à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/quantiles_all.png [Quantiles calculés pour toutes les dimensions de la demande]

Cependant, cela vous indique le 90e percentile de la sous-dimension eveeey (+ job +, + instance,` + path`, + méthode n et` + status + ). Encore une fois, nous ne sommes peut-être pas intéressés par toutes ces dimensions et souhaitons en regrouper certaines. Heureusement, l’opérateur d’agrégation `+ sum + de Prometheus peut être composé avec la fonction + histogram_quantile () + pour nous permettre d’agréger des dimensions pendant le temps de la requête!

La requête suivante calcule la latence du 90e percentile, mais ne divise le résultat qu’en dimensions + job +, + instance + et + chemin +:

histogram_quantile(
 0.9,
 sum without(status, method) (
   rate(demo_api_request_duration_seconds_bucket{job="demo"}[5m])
 )
)

Le graphique va maintenant ressembler à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/quantiles_some.png [Quantiles calculés pour certaines dimensions de la demande]

Le calcul des quantiles à partir d’histogrammes introduit toujours une certaine quantité d’erreur statistique. Cette erreur dépend de la taille de votre compartiment, de la distribution des valeurs observées ainsi que des quantiles cibles que vous souhaitez calculer. Pour en savoir plus à ce sujet, consultez Errors of quantile estimation dans la documentation de Prometheus.

Vous savez maintenant comment interpréter les métriques de l’histogramme et calculer leurs quantiles pour différentes plages de temps, tout en agrégeant certaines dimensions à la volée.

Étape 4 - Utilisation des métriques d’horodatage

Dans cette section, nous allons apprendre à utiliser des métriques contenant des horodatages.

Les composants de l’écosystème Prometheus exposent fréquemment des horodatages. Par exemple, il peut s’agir de la dernière exécution d’un travail par lots, de la dernière recharge d’un fichier de configuration ou du démarrage d’un ordinateur. Par convention, les heures sont représentées sous la forme Unix timestamps en secondes depuis le 1er janvier 1970 UTC.

Par exemple, le service de démonstration expose la dernière fois qu’un travail par lots simulé a réussi:

demo_batch_last_success_timestamp_seconds{job="demo"}

Ce travail par lots est simulé pour être exécuté une fois par minute, mais échoue dans 25% des tentatives. En cas d’échec, la métrique + demo_batch_last_success_timestamp_seconds + conserve sa dernière valeur jusqu’à ce qu’une autre exécution réussie se produise.

Si vous tracez l’horodatage brut, cela ressemblera un peu à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/raw_timestamp_data.png [graphe d’horodatage brut]

Comme vous pouvez le constater, la valeur d’horodatage brute n’est généralement pas très utile en soi. Au lieu de cela, vous voulez souvent savoir quel âge a la valeur d’horodatage. Un modèle courant consiste à soustraire l’horodatage de la métrique à l’heure actuelle, comme le prévoit la fonction + time () +:

time() - demo_batch_last_success_timestamp_seconds{job="demo"}

Cela donne le temps en secondes depuis la dernière exécution réussie du travail par lots:

image: https: //assets.digitalocean.com/articles/prometheus_querying/timestamp_age_graph.jpg [graphe d’âge Timestamp]

Si vous voulez convertir cet âge de secondes en heures, vous pouvez diviser le résultat par + 3600 +:

(time() - demo_batch_last_success_timestamp_seconds{job="demo"}) / 3600

Une expression comme celle-ci est utile pour les graphes et les alertes. Lorsque vous visualisez l’âge de l’horodatage comme ci-dessus, vous recevez un graphique en dents de scie, avec des lignes augmentant linéairement et des réinitialisations régulières sur + 0 + lorsque le travail par lots se termine avec succès. Si une pointe en dents de scie devient trop grande, cela indique un travail par lots qui ne s’est pas terminé depuis longtemps. Vous pouvez également alerter à ce sujet en ajoutant un filtre de seuil +> + à l’expression et en alertant sur la série chronologique résultante (nous ne couvrirons cependant pas les règles d’alerte dans ce tutoriel).

Pour répertorier simplement les instances pour lesquelles le travail par lots ne s’est pas terminé au cours des 1,5 dernières minutes, vous pouvez exécuter la requête suivante:

time() - demo_batch_last_success_timestamp_seconds{job="demo"} > 1.5 * 60

image: https: //assets.digitalocean.com/articles/prometheus_querying/batch_jobs.png [Affichage des travaux par lots en retard]

Vous savez maintenant comment transformer les métriques d’horodatage brutes en âges relatifs, ce qui est utile à la fois pour les graphiques et les alertes.

Étape 5 - Tri et utilisation des fonctions topk / bottomk

Dans cette étape, vous apprendrez à trier les résultats de la requête ou à sélectionner uniquement les valeurs les plus grandes ou les plus petites d’un ensemble de séries.

Dans la vue tabulaire * Console *, il est souvent utile de trier les séries de sortie en fonction de leur valeur. Vous pouvez y parvenir en utilisant les fonctions + sort () + (tri croissant) et + sort_desc () + (tri décroissant). Par exemple, pour afficher les taux de demande par chemin triés par valeur, du plus élevé au plus bas, vous pouvez interroger:

sort_desc(sum by(path) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))

La sortie triée ressemblera à ceci:

image: https: //assets.digitalocean.com/articles/prometheus_querying/sorted_request_rates.png [Taux de demandes triées]

Ou peut-être que vous n’êtes même pas intéressé à montrer toutes les séries du tout, mais seulement les plus grandes ou les plus petites séries. Pour cela, Prométhée fournit les fonctions + topk () + et + bottomk () +. Ils prennent chacun une valeur K (le nombre de séries que vous souhaitez sélectionner) et une expression arbitraire qui renvoie un ensemble de séries chronologiques à filtrer. Par exemple, pour afficher uniquement les trois taux de demande les plus élevés par chemin et par méthode, vous pouvez interroger:

topk(3, sum by(path, method) (rate(demo_api_request_duration_seconds_count{job="demo"}[5m])))

image: https: //assets.digitalocean.com/articles/prometheus_querying/top_3_request_rates.png [Les trois principaux taux de demande]

Bien que le tri soit only utile dans la vue * Console *, + topk () + et + bottomk () + peuvent également être utiles dans les graphiques. Sachez simplement que la sortie n’indiquera pas la moyenne des séries K supérieure ou inférieure sur toute la plage de temps du graphique. Au lieu de cela, la sortie calculera à nouveau les séries de sortie supérieure ou inférieure K pour chaque pas de résolution le long du graphique. Ainsi, votre série K supérieure ou inférieure peut réellement varier sur la plage du graphique, et votre graphique peut afficher plus que la série K au total.

Nous avons maintenant appris à trier ou à ne sélectionner que les K séries les plus grandes ou les plus petites.

Étape 6 - Inspection de la santé des instances supprimées

Dans cette étape, nous allons apprendre à inspecter l’état de santé de nos instances au fil du temps.

Pour rendre la section plus intéressante, terminons la première de vos trois instances de service de démonstration en arrière-plan (celle qui écoute sur le port 8080):

pkill -f -- -listen-address=:8080

Chaque fois que Prometheus gratte une cible, il stocke un échantillon synthétique avec le nom de métrique + up + et les étiquettes + job + et + + + + 'de l’instance grattée. Si la suppression a réussi, la valeur de l’échantillon est définie sur `+ 1 +. Il est réglé sur + 0 + si la récupération échoue. Ainsi, nous pouvons facilement demander quelles instances sont actuellement "up" ou "down":

up{job="demo"}

Cela devrait maintenant montrer une instance comme étant en panne:

image: https: //assets.digitalocean.com/articles/prometheus_querying/instance_health.png [Affichage de l’état de la santé]

Pour afficher les instances only vers le bas, vous pouvez filtrer la valeur + 0 +:

up{job="demo"} == 0

Vous ne devriez maintenant voir que l’instance que vous avez terminée:

image: https: //assets.digitalocean.com/articles/prometheus_querying/down_instances.png [Afficher les instances]

Ou, pour obtenir le nombre total d’instances en panne:

count by(job) (up{job="demo"} == 0)

Cela vous montrera un nombre de + 1 +:

image: https: //assets.digitalocean.com/articles/prometheus_querying/down_instance_count.png [Affichage du nombre d’instances vers le bas]

Ces types de requêtes sont utiles pour les alertes de base sur l’état de santé.

Vous savez maintenant comment interroger l’état d’intégrité de l’instance.

Conclusion

Dans ce tutoriel, nous nous sommes appuyés sur les progrès de link: / communauté / tutoriels / procédure d’interrogation de Prometheus sur Ubuntu-14-04-part-1 [Comment interroger Prométhée sur Ubuntu 14.04 Partie 1] et plus techniques et modèles de requête avancés. Nous avons appris à filtrer les séries en fonction de leur valeur, à calculer les quantiles à partir d’histogrammes, à gérer les métriques basées sur l’horodatage, etc.

Bien que ces didacticiels ne puissent pas couvrir tous les cas d’utilisation de requêtes possibles, nous espérons que les exemples de requêtes vous seront utiles lors de la création de requêtes, de tableaux de bord et d’alertes dans le monde réel avec Prometheus. Pour plus de détails sur le langage de requête de Prometheus, consultez la Prometheus documentation du langage de requête.