Je vous propose de découvrir l'analyse du rapport de Roman Khavronenko "ExtendedPromQL"


En bref sur moi. Je m'appelle Roman. Je travaille chez CloudFlare, je vis à Londres. Mais je suis aussi mainteneur de VictoriaMetrics.
Et je suis l'auteur pour Grafana et – c'est un petit proxy pour ClickHouse.

Nous commencerons par la première partie, intitulée « Les difficultés de traduction », où je parlerai du fait que toute langue, ou même simplement un moyen de communication, est très important. Parce que c'est ainsi que vous transmettez vos pensées à une autre personne ou système, comment vous formulez votre demande. Les gens sur Internet débattent de la langue à privilégier – Java ou une autre. Pour moi, j'ai décidé qu'il fallait choisir en fonction de la tâche, car tout cela est spécifique.

Commençons par le tout début. Qu'est-ce que PromQL ? PromQL – c'est le langage de requête de Prometheus. C'est ainsi que nous formons des requêtes dans Prometheus pour obtenir des données de séries temporelles.

Que sont les données de séries temporelles ? Si l'on prend cela littéralement, ce sont trois paramètres.
C'est :
- Ce que nous regardons.
- Quand nous le regardons.
- Et quelle valeur cela montre.

Si l'on regarde ce graphique (ce graphique est de mon téléphone montrant les statistiques de mes pas), on peut rapidement répondre à ces questions.
Nous regardons les pas. Nous voyons la valeur et nous voyons le moment où nous regardons cela. C'est-à-dire qu'en regardant ce graphique, on peut facilement dire qu'oulundi, j'ai fait environ 15 000 pas. Ce sont des données de séries temporelles.

Maintenant, essayons de "transformer" ces données dans un autre modèle de données sous forme de tableau. Ici, nous avons aussi ce que nous regardons. J'ai légèrement ajouté des données supplémentaires que nous appellerons des métadonnées, c'est-à-dire que ce n'est pas moi qui ai marché, mais deux personnes, disons, Jay et Silent Bob. Voici ce que nous regardons ; ce que cela montre et quand cela montre cette valeur.

Maintenant, essayons de stocker toutes ces données dans une base de données. À titre d'exemple, j'ai pris la syntaxe de ClickHouse. Et ici nous créons une table appelée « Steps », c'est-à-dire ce que nous regardons. Il y a le temps où nous le regardons ; ce que cela montre et quelques métadonnées, où nous allons stocker qui c'est : Jay et Silent Bob.

Et pour essayer de visualiser tout cela, nous utiliserons Grafana, car d'abord, c'est beau.

Nous allons également utiliser ce plugin. Il y a deux raisons à cela. La première est que je l'ai écrit. Et je sais à quel point il est difficile d'extraire des données de séries temporelles de ClickHouse pour les afficher dans Grafana.

Nous allons les afficher dans le Graph Panel. C'est le panneau le plus populaire dans Grafana, qui montre la dépendance d'une valeur par rapport au temps, donc nous avons seulement besoin de deux paramètres.

Écrivons la requête la plus simple : comment afficher les statistiques de pas dans Grafana, en conservant ces données dans ClickHouse, dans la table que nous avons créée. Et nous écrivons cette requête simple. Nous sélectionnons à partir des pas. Nous choisissons la valeur et le moment de ces valeurs, c'est-à-dire les mêmes trois paramètres dont nous avons parlé.

Et nous obtiendrons un graphique semblable à ceci. Qui sait pourquoi il est si étrange ?

C'est exact, il faut trier par temps.

Et au final, nous avons un graphique un peu mieux, mais toujours étrange. Qui sait pourquoi ? C'est vrai, il y a deux participants, et nous envoyons deux séries temporelles dans Grafana, parce que si nous examinons à nouveau le modèle de données, chaque série temporelle est une combinaison unique de nom et de toutes les paires clé-valeur des labels.

Nous devons donc choisir une personne spécifique. Nous choisissons Jay.

Et nous traçons à nouveau. Maintenant, le graphique ressemble à la réalité. C'est un graphique normal et tout fonctionne bien.

Et, vous savez probablement comment faire à peu près la même chose, mais dans Prometheus à travers PromQL. À peu près comme ça. Un peu plus simple. Et nous allons décomposer le tout. Nous avons pris les pas. Et filtrer par Jay. Ici, nous ne spécifions pas que nous avons besoin de la valeur et nous ne choisissons pas le temps.

Maintenant, essayons de calculer la vitesse de déplacement de Jay ou Silent Bob. Dans ClickHouse, nous devrons faire une runningDifference, c'est-à-dire calculer la différence entre les paires de points et les diviser par le temps pour obtenir la vitesse exacte. La requête ressemblera à peu près à ça.

Et cela montrera environ ces valeurs, c'est-à-dire que Silent Bob ou Jay font environ 1,8 pas par seconde.

Et dans Prometheus, vous savez aussi comment faire cela. C'est beaucoup plus simple qu'auparavant.
Pour rendre cela aussi simple à faire dans Grafana, j'ai ajouté un wrapper qui ressemble beaucoup à PromQL. Il s'appelle Rate Macros ou comme vous voulez l'appeler. Dans Grafana, vous écrivez simplement « rate », mais en profondeur, cela se transforme en une grosse requête. Vous n'avez même pas besoin de la regarder, elle est quelque part là-bas, mais vous gagnez beaucoup de temps, car écrire de si grandes requêtes SQL est toujours coûteux. Vous pouvez facilement faire une erreur et ensuite mettre du temps à comprendre ce qui se passe.

Et voici une requête qui ne tenait même pas sur une diapositive et j'ai dû la diviser en deux colonnes. C'est aussi une requête dans ClickHouse, qui fait la même chose que le rate, mais pour les deux séries temporelles : Silent Bob et Jay, afin que nous ayons deux séries temporelles sur notre panneau. Et cela devient déjà très compliqué, à mon avis.

Et pour Prometheus, cela sera sum(rate). Pour ClickHouse, j'ai créé un macro séparé appelé RateColumns, qui ressemble à une requête dans Prometheus.

Nous avons regardé et il semble que PromQL soit très élégant, mais il a bien sûr des limitations.
C'est :
- SELECT limité.
- JOINS limités.
- Pas de support HAVING.
Et si vous avez travaillé longtemps avec lui, vous savez qu'il est parfois très difficile de faire quelque chose dans PromQL, alors qu'en SQL, on peut pratiquement tout faire, car toutes ces options dont nous avons parlé peuvent être réalisées en SQL. Mais serait-ce pratique à utiliser ? Cela me fait penser que le langage le plus puissant n'est pas toujours le plus facile à utiliser.

C'est pourquoi il faut parfois choisir le langage en fonction des tâches. C'est comme le combat entre Batman et Superman. Il est évident que Superman est plus fort, mais Batman a réussi à le vaincre parce qu'il est plus pratique et savait exactement ce qu'il faisait.

Et la prochaine partie concerne l'extension de PromQL.

Encore une fois sur VictoriaMetrics. Qu'est-ce que VictoriaMetrics ? C'est une base de données de séries temporelles, elle est en OpenSource, nous distribuons ses versions single et cluster. Selon nos benchmarks, elle est la plus rapide sur le marché actuel et au niveau de la compression, c'est similaire, c'est-à-dire que des utilisateurs rapportent une compression d'environ 0,4 octet par point, tandis que pour Prometheus, c'est de 1,2 à 1,4.
Nous ne supportons pas seulement Prometheus. Nous supportons InfluxDB, Graphite, OpenTSDB.
Il est possible de "décrire" en nous, c'est-à-dire que vous pouvez transférer des anciennes données.
Et nous travaillons aussi parfaitement avec Prometheus et Grafana, c'est-à-dire que nous supportons le moteur PromQL. Et dans Grafana, vous pouvez simplement changer l'endpoint Prometheus en VictoriaMetrics et tous vos tableaux de bord fonctionneront comme avant.
Mais vous pouvez également utiliser des fonctionnalités supplémentaires que VictoriaMetrics offre.
Nous passerons rapidement en revue les fonctions que nous avons ajoutées.

Omettre le paramètre d'intervalle – vous pouvez passer le paramètre d'intervalle dans Grafana. Lorsque vous ne voulez pas obtenir de graphiques étranges lors du zoom avant/arrière dans le panneau, il est recommandé d'utiliser la variable $__interval. C'est une variable interne de Grafana et elle choisit elle-même la plage de données. VictoriaMetrics peut également comprendre quelle devrait être cette plage. Vous n'avez donc pas besoin de mettre à jour toutes vos requêtes. Ce sera beaucoup plus simple.

La deuxième fonction est la référence d'intervalle. Vous pouvez utiliser cet intervalle dans vos expressions. Vous pouvez le multiplier, le diviser, le passer, le référencer.

Ensuite, il y a la famille des fonctions rollup. Les fonctions rollup transforment n'importe quelle série temporelle en trois séries temporelles distinctes : min, max et avg. Je trouve cela très pratique, car cela peut parfois révéler des anomalies.

Et si vous faites simplement irate ou rate, vous pourriez probablement manquer certains cas où la série temporelle se comporte différemment de ce que vous aviez prévu. Avec cette fonction, il est beaucoup plus facile de voir, par exemple, que le max est très éloigné de l'avg.

Ensuite, il y a la variable par défaut. Par défaut, cela signifie quelle valeur nous devons afficher dans Grafana lorsque nous n'avons pas de série temporelle pour le moment. Quand cela se produit ? Supposons que vous exportiez une certaine métrique sur les erreurs. Et vous avez une application si géniale que lorsque vous l'avez lancée, vous n'avez aucune erreur et même pas d'erreurs lors des trois premières heures ou même d'un jour. Et vous avez des tableaux de bord qui montrent le rapport entre le succès et l'erreur. Et ils ne vous montreront rien, car vous n'avez pas de métrique d'erreur. Mais dans les valeurs par défaut, vous pouvez indiquer n'importe quoi.

Keep_last_Value – conserve la dernière valeur de la métrique si elle disparaît. Si Prometheus ne la trouve pas au prochain scrape pendant 5 minutes, alors ici nous mémoriserons sa dernière valeur et vos graphiques ne seront pas à nouveau cassés.

Scrape_interval – indique à quelle fréquence Prometheus collecte des données sur votre métrique, à quelle fréquence. Ici, vous pouvez voir des échecs, par exemple.

Label replace – une fonction populaire. Mais nous trouvons qu'elle est un peu complexe, car elle prend de nombreux arguments. Vous devez non seulement vous rappeler 5 arguments, mais aussi vous souvenir de leur ordre.

Alors, pourquoi ne pas les simplifier ? C'est-à-dire, les décomposer en petites fonctions avec une syntaxe claire.

Et maintenant, la partie intéressante. Pourquoi considérons-nous que cela est un PromQL étendu ? Parce que nous supportons les expressions de table communes. Vous pouvez scanner le QR code (), consulter les liens avec des exemples, avec un playground où vous pouvez exécuter des requêtes directement dans VictoriaMetrics sans l'installer, simplement dans votre navigateur.

Qu'est-ce que cela signifie ? Cette requête ci-dessus est une requête assez populaire. Je pense que dans n'importe quel tableau de bord de nombreuses entreprises, vous utilisez le même filtre pour tout. Généralement, c'est ainsi. Mais quand vous devez ajouter un nouveau filtre, vous devez mettre à jour chaque panneau ou télécharger le tableau de bord, l'ouvrir en JSON, faire une recherche et remplacer, ce qui prend aussi du temps. Pourquoi ne pas conserver cette valeur dans une variable et la réutiliser ? Cela me semble beaucoup plus simple et compréhensible.

Par exemple, quand je dois mettre à jour les filtres dans Grafana dans toutes les requêtes, et que le tableau de bord peut être immense ou qu'il peut même y en avoir plusieurs. Et comment aimerais-je résoudre ce problème dans Grafana ?

Je résous ce problème comme ça : je crée un commonFilter et j'y définis ce filtre, puis je le réutilise dans les requêtes. Mais si vous faites de même maintenant, cela ne fonctionnera pas, car Grafana ne vous permet pas d'utiliser des variables à l'intérieur des variables de requêtes. Et c'est un peu étrange.

C'est pourquoi j'ai élaboré une variante qui le permet. Si cela vous intéresse ou si vous souhaitez cette fonctionnalité, alors soutenez ou n'aimez pas, si cette idée ne vous convient pas.

Ensuite, parlons de PromQL étendu. Ici, nous définissons non seulement une variable, mais carrément une fonction. Nous l'appelons ru (utilisation des ressources). Cette fonction accepte les ressources libres, les limites de ressources et un filtre. La syntaxe est plutôt simple. Et il est très facile d'utiliser cette fonction et de calculer le pourcentage de mémoire libre disponible pour nous. C'est-à-dire, combien de mémoire nous avons, quelle est la limite et comment filtrer. Cela semble beaucoup plus pratique, si vous écriviez tout cela en réutilisant les mêmes filtres, car cela se transformerait en une grosse requête.

Voici un exemple d'une requête très complexe. Elle provient du tableau de bord officiel de NodeExporter pour Grafana. Mais je comprends mal ce qui se passe ici. Autrement dit, bien sûr, je comprends si je m'y attarde, mais le nombre de parenthèses peut rapidement diminuer la motivation à comprendre ce qui se passe ici. Alors, pourquoi ne pas le rendre plus simple et plus clair ?

Par exemple, comme cela, en mettant en valeur des éléments ou des parties dans des variables. Et ensuite, effectuer vos opérations de base. Cela ressemble déjà davantage à de la programmation, c'est ce que j'aimerais voir à l'avenir dans Grafana.

Voici un second exemple, comment nous pourrions rendre cela encore plus simple, si nous avions déjà cette fonction ru, qui existe déjà dans VictoriaMetrics. Et vous transmettez simplement la valeur mise en cache que vous avez déclarée dans le CTE.

J'ai déjà mentionné à quel point il est important d'utiliser le bon langage de programmation. Et probablement, dans chaque entreprise, il se passe quelque chose de différent dans Grafana. Vous donnez probablement encore accès à Grafana à vos développeurs, qui font des choses à leur manière. Et tous le font différemment. J'aimerais qu'on parvienne à un certain standard.
Supposons que vous n'ayez pas seulement des ingénieurs systèmes, peut-être avez-vous même des experts, des devops ou des SRE. Peut-être avez-vous des experts qui savent ce qu'est la surveillance, savent ce qu'est Grafana, c'est-à-dire qu'ils y travaillent depuis des années et qu'ils savent exactement comment faire correctement. Ils l'ont déjà écrit 100 fois et ont tout expliqué, mais personne ne semble les écouter.
Et si ces connaissances pouvaient être directement intégrées dans Grafana, pour que d'autres utilisateurs puissent réutiliser les fonctions ? Et si vous deviez calculer le pourcentage de mémoire libre, vous appliqueriez simplement la fonction. Que se passerait-il si les créateurs d'exporteurs fournissaient également un ensemble de fonctions sur la façon de travailler avec leurs métriques, car ils savent exactement ce que c'est que ces métriques et comment les calculer correctement ?
Ce concept n'existe pas vraiment. C'est quelque chose que j'ai créé moi-même. Cela concerne le support des bibliothèques dans Grafana. Par exemple, les personnes qui ont créé NodeExporter ont réalisé ce dont je parle. Et elles ont également fourni un ensemble de fonctions.

Cela ressemble à peu près à ça. Vous connectez cette bibliothèque dans Grafana, vous entrez en mode édition et il est très simple de voir dans le JSON comment travailler avec cette métrique. C'est-à-dire un ensemble de fonctions, leur description et la façon dont elles se déploient.

Je pense que cela pourrait être utile, car dans Grafana, vous pourriez écrire simplement comme ça. Et Grafana vous "dit" qu'il y a une fonction de telle bibliothèque - utilisons-la. Je pense que ce serait vraiment génial.

Un peu sur VictoriaMetrics. Nous faisons beaucoup de choses intéressantes. Lisez nos articles sur la compression, nos compétitions avec d'autres applications de séries temporelles, notre explication sur comment travailler avec PromQL, car il y a encore beaucoup de débutants, ainsi que sur la scalabilité verticale et notre affrontement avec Thanos.

Questions :
Je vais commencer ma question par une simple histoire de vie. Lorsque j'ai commencé à utiliser Grafana pour la première fois, j'ai écrit une requête très convaincante de cinq lignes. Au final, j'ai obtenu un graphique très convaincant. Ce graphique a presque été mis en production. Mais en y regardant de plus près, il s'est avéré que ce graphique affichait des absurdités absolues, qui n'avaient rien à voir avec la réalité, bien que les chiffres soient dans la plage que nous espérions voir. Et ma question est la suivante. Nous avons des bibliothèques, nous avons des fonctions, mais comment écrivons-nous des tests pour Grafana ? Vous avez écrit une requête complexe, sur laquelle dépend une décision commerciale - passer une commande pour un véritable conteneur de serveurs ou non. Et comment savons-nous que cette fonction, qui dessine le graphique, ressemble à la vérité. Merci.
Merci pour votre question. Il y a deux parties. D'une part, je remarque, d'après ma pratique, que la plupart des utilisateurs, lorsqu'ils regardent leurs graphiques, ne comprennent pas ce qu'ils montrent. Les gens sont étonnamment doués pour inventer des excuses pour toute anomalie qui se produit sur les graphiques, même s'il s'agit d'une erreur dans la fonction. D'autre part, je pense que l'utilisation de telles fonctions conviendrait beaucoup mieux à la solution de votre problème, au lieu que chacun de vos développeurs effectue son propre plan de capacité et se trompe avec une certaine probabilité.
Comment vérifier ?
Comment vérifier ? Probablement pas moyen.
Sous forme de test dans Grafana.
Quel rapport avec Grafana ? Grafana transmet cette requête directement au DataSource.
En ajoutant un peu aux paramètres.
Non, rien n'est ajouté dans Grafana. Il peut y avoir des paramètres GET, comme par exemple step. Il n'est pas clairement spécifié, mais vous pouvez le redéfinir, ou ne pas le redéfinir, mais il est ajouté automatiquement. Vous ne pouvez pas écrire de tests ici. Je pense qu'il ne faut pas compter sur Grafana comme source de vérité.
Merci pour la présentation ! Merci pour la compression ! Vous avez mentionné le mappage des variables dans le graphique, à savoir qu'il n'est pas possible d'utiliser une variable dans une autre variable dans Grafana. Comprenez-vous de quoi je parle ?
Oui.
C'était à l'origine un véritable casse-tête lorsque je voulais créer une alerte dans Grafana. Et il faut faire des alertes pour chaque hôte séparément. Cette fonction que vous avez réalisée fonctionne-t-elle pour les alertes dans Grafana ?
Si Grafana ne traite pas les variables d'une autre manière, alors oui, cela fonctionnera. Mais mon conseil est de ne pas utiliser l'alerte dans Grafana du tout, il vaut mieux utiliser alertmanager.
Oui, je l'utilise, mais c'est juste que cela m'a semblé plus facile à configurer dans Grafana, mais merci pour le conseil !
Source : habr.com
