À propos du langage MQL (Monitoring Query Language)

Cette page fournit des informations générales sur le langage MQL (Monitoring Query Language), y compris les sujets suivants :

Ces informations s'appliquent que vous utilisiez MQL à partir de la console Google Cloud ou de l'API Cloud Monitoring. Pour en savoir plus sur la structure des requêtes MQL, consultez la page Exemples.

Raccourcis des opérations et fonctions de table

Les requêtes sont généralement constituées de chaînes connectées d'opérations de table reliées par des barres (|), chacune commençant par le nom de l'opération de table suivie d'une liste d'expressions. Les expressions peuvent contenir des appels de fonction qui répertorient explicitement tous leurs arguments. Cependant, le langage MQL permet d'exprimer les requêtes avec un certain nombre de raccourcis.

Cette section décrit les raccourcis des opérations de table, explique comment utiliser les fonctions comme opérations de table, et présente le raccourci permettant d'utiliser les colonnes de valeurs comme arguments des fonctions.

Pour obtenir la liste complète, consultez la section Raccourcis des opérations de table.

Raccourcis des opérations de table

Lorsque vous utilisez les opérations fetch, group_by et filter, vous pouvez omettre l'opération de table explicite lorsque les arguments sont suffisants pour déterminer l'opération prévue. Par exemple, la requête suivante :

gce_instance::compute.googleapis.com/instance/cpu/utilization

équivaut à :

fetch gce_instance::compute.googleapis.com/instance/cpu/utilization

Les opérations group_by suivantes sont équivalentes :

         [zone], mean(val())
group_by [zone], mean(val())

Vous pouvez omettre le mot filter si vous mettez le test du filtre entre parenthèses. Par exemple, les deux opérations filter suivantes sont équivalentes :

       (instance_name =~ 'apache.*')
filter instance_name =~ 'apache.*'

Vous pouvez combiner ces formats de raccourci dans vos requêtes. Par exemple, la requête suivante :

gce_instance::compute.googleapis.com/instance/cpu/utilization
| (instance_name =~ 'apache.*')
|  [zone], mean(val())

équivaut à ce format plus explicite :

fetch gce_instance::compute.googleapis.com/instance/cpu/utilization
| filter instance_name =~ 'apache.*'
| group_by [zone], mean(val())

Pour plus d'informations sur les raccourcis des opérations de table, consultez la section Raccourcis des opérations de table dans la documentation de référence sur le langage MQL.

Utiliser une fonction comme opération de table

Une opération de table commence généralement par le nom d'une opération de table. Cependant, MQL permet à une opération de table de commencer par un nom de fonction.

Vous pouvez utiliser un nom de fonction lorsque la fonction nommée consiste à effectuer une transformation des colonnes de valeurs de la table d'entrée. Ce remplacement est un raccourci pour les opérations de table group_by, align ou value, en fonction du type de fonction nommé.

Le format général ressemble à ceci :

|  FUNCTION_NAME ARG, ARG ... 

Dans l'opération de table, la fonction utilise les colonnes de valeurs de la table d'entrée comme arguments (suivis des arguments de la fonction elle-même). Lorsque vous utilisez une fonction comme opération de table, vous séparez les arguments par une virgule dans l'opération de table, plutôt que d'utiliser les parenthèses (()) généralement utilisés avec les fonctions.

L'opération de table complète générée par le développement du raccourci dépend du type de fonction :

  • group_by : si vous utilisez une fonction d'agrégation avec une opération group_by qui regroupe l'ensemble des colonnes d'identifiants de séries temporelles (c'est-à-dire qu'elle utilise [] pour effectuer le regroupement), vous pouvez utiliser la fonction en tant que raccourci. Exemple :

    | distribution powers_of(1.1)

    est un raccourci de

    | group_by [], distribution(val(0), powers_of(1.1))
  • align : si vous utilisez une fonction d'alignement comme argument de l'opération align, vous pouvez utiliser la fonction en tant que raccourci. Exemple :

    | delta

    est un raccourci de

    | align delta()

    De même,

    | rate 10m

    est un raccourci de

    | align rate(10m)

    Notez que les fonctions d'alignement utilisent la série temporelle d'entrée comme argument implicite. Les colonnes de valeurs ne sont donc pas explicitement indiquées ici.

  • value : toutes les autres fonctions peuvent être utilisées comme raccourcis pour l'opération de table value. Exemple :

    | mul 3.3

    est un raccourci de

    | value mul(val(0), 3.3)

    De même,

    | div

    est un raccourci de

    | value div(val(0), val(1))

    Notez que le raccourci div utilise une opération de table d'entrée avec deux colonnes de valeurs et génère une opération de table avec une colonne de valeurs correspondant au ratio.

Raccourci des fonctions de colonnes de valeurs

Vous pouvez utiliser .function comme raccourci de function(val()) si l'entrée ne comporte qu'une seule colonne de valeur, ou comme raccourci de function(val(0), val(1)) s'il existe deux colonnes de valeurs ou plus.

Le point initial signifie "Appeler la fonction suivante, en fournissant la ou les colonnes de valeurs du point d'entrée comme argument(s) de la fonction".

Par exemple,   .mean est un raccourci de mean(val()). Les expressions suivantes sont équivalentes :

group_by [zone], .mean
group_by [zone], mean(val())

Si la table d'entrée comporte plusieurs colonnes de valeurs, chaque colonne devient un argument de la fonction dans ce raccourci. Par exemple, si la table d'entrée comporte deux colonnes de valeurs,

.div

est un raccourci de

div(val(0), val(1))

Ce raccourci vous permet de fournir des arguments qui ne font pas référence à des colonnes de valeurs. Les arguments supplémentaires sont fournis après les arguments de colonnes de valeurs. Par exemple, si la table d'entrée comporte une colonne de valeurs,

.div(3)

est équivalent à :

div(val(0), 3)

Variantes sur une opération fetch

L'opération fetch renvoie généralement une table de séries temporelles nommée par une paire de valeurs composée du type de ressource surveillée et du type de métrique. Exemple :

fetch gce_instance :: compute.googleapis.com/instance/cpu/utilization

Si la métrique ne s'applique qu'à un seul type de ressource surveillée, vous pouvez omettre la ressource surveillée de la requête. La requête suivante est équivalente à la requête précédente, car la métrique d'utilisation du processeur ne s'applique qu'aux ressources surveillées gce_instance :

fetch compute.googleapis.com/instance/cpu/utilization

L'opération fetch ne peut spécifier qu'un type de ressource surveillée, avec la métrique spécifiée dans les opérations metric ultérieures. L'exemple suivant est équivalent aux exemples fetch précédents :

fetch gce_instance
| metric metric compute.googleapis.com/instance/cpu/utilization

Diviser l'opération fetch de cette manière peut être utile lorsque vous souhaitez récupérer deux métriques différentes pour la même ressource surveillée. Par exemple, la requête suivante calcule le nombre de paquets par seconde de processeur consommée :

fetch gce_instance
| {
    metric compute.googleapis.com/instance/network/received_packets_count ;
    metric compute.googleapis.com/instance/cpu/usage_time
  }
| ratio

La division de fetch vous permet également de n'appliquer un filtrage qu'aux libellés de la ressource surveillée :

fetch gce_instance
| filter resource.zone =~ "asia.*"
| {
    metric compute.googleapis.com/instance/network/received_packets_count ;
    metric compute.googleapis.com/instance/cpu/usage_time
  }
| ratio

Une opération fetch qui ne nomme qu'un type de ressource surveillée doit être suivie d'une opération metric, éventuellement avec des opérations filter intermédiaires.

Requêtes de format strict

Une requête de format strict est une requête sans aucun raccourci ni valeur implicite utilisés dans les requêtes concises. Les requêtes strictes présentent les caractéristiques suivantes:

  • Tous les raccourcis sont remplacés.
  • Tous les arguments implicites sont rendus explicites.
  • Les colonnes sont désignées par des noms complets.
  • Les nouvelles colonnes portent des noms explicites.
  • Toutes les opérations d'alignement implicitement fournies sont explicitement données.

L'utilisation du format strict rend la requête plus résiliente aux modifications de la structure des tables d'entrée. Cela peut ainsi permettre de clarifier la fonction de la requête. L'exécution d'une requête de format strict ne rend pas la requête plus efficace.

Lorsque vous enregistrez une requête pour un graphique, elle est convertie au format strict. La boîte de dialogue de confirmation pour l'opération d'enregistrement affiche le format strict.

Les requêtes concises pour les règles d'alerte ne sont pas converties au format strict. Les requêtes pour les règles d'alerte sont stockées au fur et à mesure que vous les fournissez. Vous pouvez utiliser la forme concise ou stricte.

Lorsque des raccourcis et des formats stricts sont disponibles, vous pouvez rencontrer des requêtes MQL équivalentes qui ne se ressemblent pas. Par exemple, la requête suivante, qui calcule le nombre de paquets reçus par seconde de processeur consommée, utilise de nombreux raccourcis :

gce_instance
| (zone =~ ".*-a")
| {
    compute.googleapis.com/instance/network/received_packets_count ;
    compute.googleapis.com/instance/cpu/usage_time
  }
| join
| div

Lorsque vous enregistrez cette requête dans un graphique ou dans le cadre d'une règle d'alerte, la requête de format strict obtenue fait exactement la même chose. Cependant, le format strict peut sembler légèrement différent, comme illustré dans l'exemple suivant :

fetch gce_instance
| filter (resource.zone =~ '.*-a')
| { t_0:
      metric 'compute.googleapis.com/instance/network/received_packets_count'
      | align delta() ;
    t_1:
      metric 'compute.googleapis.com/instance/cpu/usage_time'
      | align delta() }
| join
| value [v_0: div(t_0.value.received_packets_count, t_1.value.usage_time)]

Lorsque vous modifiez la définition enregistrée du graphique, l'éditeur de code affiche le format au format strict.

Travailler avec la colonne resource.project_id

Le nom à afficher des projets Google Cloud apparaît dans les menus, mais ne permet pas de les identifier de manière unique. Le nom à afficher d'un projet peut être "Démonstration Monitoring".

Les projets comportent également deux champs qui servent d'identifiants :

  • ID du projet : identifiant de chaîne unique. Il est souvent basé sur le nom à afficher. Il est défini lors de la création du projet, généralement en concaténant les éléments du nom du projet et en ajoutant éventuellement des chiffres à la fin, si cela est nécessaire pour pouvoir identifier le projet de manière unique. Un ID de projet peut se présenter au format "monitoring-demo" ou "monitoring-demo-2349". L'ID du projet est parfois appelé nom du projet.
  • Numéro de projet : identifiant numérique unique.

Chaque type de ressource surveillée inclut un libellé project_id. Le numéro du projet propriétaire de la ressource et des données de cette ressource est représenté sous forme de chaîne.

Dans les requêtes MQL, ce libellé est référence comme resource.project_id. La valeur du libellé resource.project_id est en général le numéro de projet au format textuel, mais MQL peut dans certains cas convertir cette valeur afin de renvoyer l'ID du projet.

Dans les cas suivants, MDL traite la valeur du libellé resource.project_id comme l'ID de projet plutôt que le numéro de projet :

  • La légende d'un graphique affiche l'ID du projet plutôt que son numéro pour la valeur du libellé resource.project_id.

  • Les comparaisons d'égalité entre la valeur du libellé resource.project_id et une chaîne littérale reconnaissent à la fois le numéro du projet et l'ID du projet. Par exemple, les comparaisons suivantes renvoient vrai toutes les deux pour des ressources appartenant au projet :

    • resource.project_id == "monitoring-demo"
    • resource.project_id == "530310927541"

    Ce cas s'applique aux opérateurs == et !=, ainsi qu'à leurs formats de fonctions, eq() et ne().

  • Une correspondance d'expression régulière sur le libellé resource.project_id fonctionne correctement avec le numéro du projet ou l'ID du projet. Par exemple, les deux expressions suivantes renvoient true pour les ressources appartenant à ce projet :

    • resource.project_id =~ "monitoring-.*"
    • resource.project_id =~ ".*27541"

    Ce cas s'applique aux opérateurs =~ et !~, ainsi qu'au format de fonction re_full_match.

Dans tous les autres cas, la valeur réelle du libellé resource.project_id est utilisée. Par exemple, la fonction concatenate("project-", resource.project_id) renvoie project-530310927541 et non project-monitoring-demo.

Ratios et "effet de bord"

En général, il est préférable de calculer les ratios en fonction des séries temporelles collectées pour un type de métrique unique, à l'aide de valeurs de libellés. Un ratio calculé sur deux types de métriques différents peut présenter des anomalies en raison de différentes périodes d'échantillonnage et fenêtres d'alignement.

Par exemple, supposons que vous disposiez de deux types de métriques différents (nombre de RPC total et nombre de RPC en erreur), et que vous souhaitiez calculer le ratio du nombre de RPC en erreur par rapport au nombre de RPC total. Les RPC ayant échoué sont comptabilisés dans la série temporelle des deux types de métriques. Par conséquent, lorsque vous alignez la série temporelle, il se peut qu'un RPC en échec n'apparaisse pas dans le même intervalle d'alignement pour les deux séries temporelles. Cette différence peut se produire pour plusieurs raisons :

  • Étant donné que deux séries temporelles enregistrent le même événement, deux valeurs de compteur sous-jacentes mettent en œuvre la collection et ne sont pas mises à jour de manière atomique.
  • Les taux d'échantillonnage peuvent varier. Lorsque les séries temporelles sont alignées sur une période commune, les décomptes d'un seul événement peuvent apparaître dans des intervalles d'alignement adjacents dans la série temporelle des différentes métriques.

La différence du nombre de valeurs dans les intervalles d'alignement correspondants peut générer des valeurs de ratio error/total insensées, telles que 1/0 ou 2/1.

Les ratios de nombres plus élevés sont moins susceptibles de donner lieu à des valeurs absurdes. Vous pouvez obtenir des nombres plus importants par agrégation, soit en utilisant une fenêtre d'alignement plus longue que la période d'échantillonnage, soit en regroupant les données pour certaines étiquettes. Ces techniques réduisent l'effet de différences mineures du nombre de points dans un intervalle donné. En d'autres termes, une disparité de deux points est plus importante lorsque le nombre attendu de points dans un intervalle est de 3 par rapport au nombre attendu de 300.

Si vous utilisez des types de métriques intégrés, vous n'aurez peut-être pas d'autre choix que de calculer les ratios sur l'ensemble des types de métriques pour obtenir la valeur souhaitée.

Si vous concevez des métriques personnalisées pouvant comptabiliser la même chose (par exemple, des RPC qui renvoient des états d'erreur) dans deux métriques différentes, envisagez plutôt d'utiliser une seule métrique, qui inclut un décompte à la fois. Par exemple, supposons que vous comptabilisiez les RPC et que vous souhaitiez suivre le ratio entre les RPC ayant échoué et tous les RPC. Pour résoudre ce problème, créez un seul type de métrique pour comptabiliser les RPC et utilisez un libellé pour enregistrer l'état de l'appel, y compris l'état "OK". Chaque valeur d'état (erreur ou état "OK") est ensuite enregistrée en mettant à jour un seul compteur pour ce cas.

Formats de date MQL

MQL n'accepte actuellement qu'un nombre limité de formats de date. Dans les requêtes MQL, les dates sont exprimées dans l'un des formats suivants :

  • d'BASE_STRING'
  • D'BASE_STRING'

BASE_STRING est une chaîne au format 2010/06/23-19:32:15-07:00. Le premier tiret (-) séparant la date et l'heure peut être remplacé par une espace. Dans le composant temporel, certaines parties de l'horloge (19:32:15) ou du spécificateur de fuseau horaire (-07:00) peuvent être supprimées.

Les exemples suivants sont des dates valides dans les requêtes MQL :

  • d'2010/06/23-19:32:15-07:00'
  • d'2010/06/23 19:32:15-07:00'
  • d'2010/06/23 19:32:15'
  • D'2010/06/23 19:32'
  • d'2010/06/23-19'
  • D'2010/06/23 -07:00'

Le tableau suivant répertorie la grammaire utilisée pour BASE_STRING :

Structure Signification
%Y/%m/%d Date
%Y/%m/%d %H
%Y/%m/%d-%H
Date et heure
%Y/%m/%d %H:%M
%Y/%m/%d-%H:%M
Date, heure et minute
%Y/%m/%d %H:%M:%S
%Y/%m/%d-%H:%M:%S
Date, heure, minute et seconde
%Y/%m/%d %H:%M:%E*S
%Y/%m/%d-%H:%M:%E*S
Date, heure, minute et seconde fractionnaire
%Y/%m/%d %Ez Date avec fuseau horaire
%Y/%m/%d %H%Ez
%Y/%m/%d-%H%Ez
Date et heure avec fuseau horaire
%Y/%m/%d %H:%M%Ez
%Y/%m/%d-%H:%M%Ez
Date, heure et minute avec fuseau horaire
%Y/%m/%d %H:%M:%S%Ez
%Y/%m/%d-%H:%M:%S%Ez
Date, heure, minute et seconde avec fuseau horaire
%Y/%m/%d %H:%M:%E*S%Ez
%Y/%m/%d-%H:%M:%E*S%Ez
Date, heure, minute et seconde fractionnaire avec fuseau horaire

Longueur et complexité des requêtes

Les requêtes MQL peuvent être longues et complexes, mais ne sont pas illimitées.

  • Un texte de requête encodé au format UTF-8 est limité à 10 000 octets.
  • Une requête est limitée à 2 000 constructions de langage, c'est-à-dire que la complexité de l'arbre syntaxique abstrait (ASA) est limitée à 2 000 nœuds.

 Un arbre syntaxique abstrait, ou ASA, est une représentation du code source (dans ce cas, une chaîne de requête MQL), où les nœuds de l'arborescence correspondent à des structures syntaxiques dans le code.

Macros MQL

MQL inclut un utilitaire de définition de macros. Vous pouvez utiliser les macros MQL pour remplacer les opérations répétées, rendre les requêtes complexes plus lisibles et simplifier le développement des requêtes. Vous pouvez définir des macros pour des opérations de table et des fonctions.

Les définitions de macros commencent par le mot clé def.

Lorsque vous convertissez une requête au format strict, les appels de macro sont remplacés par leur texte correspondant et les définitions de macro sont supprimées.

Lorsque vous enregistrez une requête de graphique qui inclut des macros, la requête est convertie au format strict, de sorte que les macros ne soient pas conservées. Lorsque vous enregistrez une requête pour une condition dans une règle d'alerte, la requête n'est pas convertie au format strict. Par conséquent, les macros sont conservées.

Macros pour les opérations de table

Vous pouvez écrire des macros pour effectuer de nouvelles opérations de table. La syntaxe générale se présente comme suit :

def MACRO_NAME [MACRO_PARAMETER[, MACRO_PARAMETER]] = MACRO_BODY ;

Pour appeler la macro, utilisez la syntaxe suivante :

@MACRO_NAME [MACRO_ARG [, MACRO_ARG]]

Par exemple, supposons que vous exécutiez la requête suivante pour extraire les données d'utilisation du processeur :

fetch gce_instance::compute.googleapis.com/instance/cpu/utilization
| every 1m
| group_by [zone], mean(val())

La première ligne peut être remplacée par la macro suivante :

def my_fetch = fetch gce_instance::compute.googleapis.com/instance/cpu/utilization ;

Pour appeler la macro dans la requête, remplacez la valeur fetch d'origine comme suit :

def my_fetch = fetch gce_instance::compute.googleapis.com/instance/cpu/utilization ;

@my_fetch
| every 1m
| group_by [zone], mean(val())

Vous pouvez remplacer la deuxième et la troisième lignes par des macros acceptant des arguments. La définition de la macro répertorie les paramètres de la macro et y fait référence au format $MACRO_PARAMETER dans le corps de la macro. Par exemple, vous pouvez définir les macros suivantes :

def my_every time_arg = every $time_arg ;

def my_group label, aggr = group_by [$label], $aggr ;

Pour appeler ces macros et fournir les arguments, spécifiez les arguments dans une liste délimitée par des virgules dans les appels de macros. Voici la requête avec toutes les macros définies et leurs appels :

def my_fetch = fetch gce_instance::compute.googleapis.com/instance/cpu/utilization ;
def my_every time_arg = every $time_arg ;
def my_group label, aggr = group_by [$label], $aggr ;

{@my_fetch}
| @my_every 1m
| @my_group zone, mean(val())

Les macros ne sont pas conservées lorsque la requête est convertie au format strict. Par exemple, la forme stricte de la requête précédente se présente comme suit:

fetch gce_instance::compute.googleapis.com/instance/cpu/utilization
| align mean_aligner()
| every 1m
| group_by [resource.zone],
           [value_utilization_mean: mean(value.utilization)]

Macros pour les fonctions

Pour les fonctions MQL, vous spécifiez les paramètres entre parenthèses dans une liste délimitée par des virgules. Les parenthèses distinguent la macro pour une fonction d'une macro pour une opération de table. Les parenthèses doivent apparaître dans l'appel, même si aucun argument n'existe. Les macros ne sont pas conservées lorsque la requête est convertie au format strict.

def MACRO_NAME([MACRO_PARAMETER [, MACRO_PARAMETER]]) = MACRO_BODY ;

Par exemple, la requête suivante récupère les tables de deux métriques, combine les deux tables en une seule avec deux colonnes de valeurs, puis calcule le ratio entre le nombre d'octets reçus et le nombre total d'octets dans une colonne appelée received_percent :

{
  fetch k8s_pod :: kubernetes.io/pod/network/received_bytes_count ;
  fetch k8s_pod :: kubernetes.io/pod/network/sent_bytes_count
}
| join
| value [received_percent: val(0) * 100 / (val(0) + val(1))]

Vous pouvez remplacer le calcul received_percent par une macro semblable à la suivante :

def recd_percent(recd, sent) = $recd * 100 / ($recd + $sent) ;

Pour appeler une macro pour une fonction, utilisez la syntaxe suivante :

@MACRO_NAME([MACRO_ARG[, MACRO_ARG]])

Lorsque vous appelez une macro pour une fonction sans argument, vous devez spécifier les parenthèses vides pour distinguer l'appel de l'appel d'une macro pour une opération de table.

L'exemple suivant montre la requête précédente avec une macro permettant de calculer le ratio :

def recd_percent(recd, sent) = $recd * 100 / ($recd + $sent) ;

{
  fetch k8s_pod :: kubernetes.io/pod/network/received_bytes_count ;
  fetch k8s_pod :: kubernetes.io/pod/network/sent_bytes_count
}
| join
| value [received_percent: @recd_percent(val(0), val(1))]

Fonctionnalités des macros

Les macros MQL sont des éléments syntaxiques, par opposition aux éléments textuels, tels que les macros utilisées dans le préprocesseur C. Cette distinction signifie qu'un corps de macro MQL doit toujours être une expression valide d'un point de vue syntaxique. Il peut ne pas être valide d'un point de vue sémantique, ce qui dépend également des arguments de macro et de l'emplacement d'expansion de la macro.

Les macros MQL étant syntaxiques, il existe très peu de restrictions sur le type d'expression vers lequel elles peuvent être développées. Les macros syntaxiques sont simplement un autre moyen de manipuler l'arbre syntaxique abstrait. Les exemples suivants illustrent certaines des actions que vous pouvez effectuer avec les macros syntaxiques:

# Abbreviating a column name.
def my_col() = instance_name;

# Map-valued macro.
def my_map(c) = [$c, @my_col()];

# Abbreviating a string.
def my_zone() = 'us-central.*';

# Abbreviating a filter expression.
def my_filter(f) = zone =~ @my_zone() && $f;

MQL accepte également la concaténation littérale de chaînes implicite. Cette fonctionnalité peut s'avérer très utile lors de l'écriture de requêtes incluant des noms de métriques longs. Lorsqu'un littéral de chaîne et un argument de macro, qui doit également être un littéral de chaîne, apparaissent les uns à côté des autres dans le corps de la macro, l'expansion de macro les concatène dans un seul littéral de chaîne.

Dans l'exemple suivant, gce_instance est un élément lexical BARE_NAME. Il est automatiquement promu en littéral de chaîne, ce qui est utile pour créer des noms de table:

# Builds a table name in domain 'd' with the suffix 'm'.
def my_table(d, m) = gce_instance::$d '/instance/' $m;

# Table name under the given domain.
def my_compute_table(m) = @my_table('compute.googleapis.com', $m);

Pour résumer, la requête suivante utilise toutes les macros précédemment définies:

fetch @my_compute_table('cpu/utilization')
| filter @my_filter(instance_name =~ 'gke.*')
| group_by @my_map(zone)

Notez que les arguments de macro peuvent également être des expressions arbitraires, à condition qu'ils soient corrects d'un point de vue syntaxique. Par exemple, la macro my_filter peut utiliser une expression booléenne telle que instance_name =~ 'gke.*' comme premier argument.

L'abréviation des opérations de table peut également être très utile, comme le montre la requête suivante:

# Calculate the ratio between compute metrics 'm1' and 'm2'.
def my_compute_ratio m1, m2 =
  { fetch @my_compute_table($m1); fetch @my_compute_table($m2) }
  | join | div;

# Use the table op macro to calculate the ratio between CPU utilization and
# the number of reserved cores per zone.
@my_compute_ratio 'cpu/utilization', 'cpu/reserved_cores' | group_by [zone]

Enfin, les macros de fonctions peuvent se comporter comme des fonctions standards. En d'autres termes, ils permettent la promotion de fonctions, où la ou les colonnes de valeurs de la table d'entrée deviennent les premiers arguments de la macro. L'exemple suivant montre une variante de la requête précédente qui utilise une macro pour la fonction:

# Simple arithmetic macro.
def my_add_two(x) = $x + 2;

# Similar to previous query, but now using the new arithmetic macro with
# function argument promotion.
fetch @my_compute_table('cpu/utilization')
| filter @my_filter(instance_name =~ 'gke.*')
| group_by @my_map(zone), [.sum.@my_add_two]

Limites

La fonctionnalité de macro MQL n'est pas compatible avec les éléments suivants :

  • Imbrication de définitions de macros: vous ne pouvez pas définir une macro dans le corps d'une autre macro.
  • Macros définies de manière récursive. Aucune macro ne peut faire référence dans son corps à une macro qui n'est pas encore entièrement définie, y compris elle-même.
  • Utilisation de fonctions définies par des macros en tant qu'opérations de table
  • Utilisation d'arguments de macros en tant que noms de fonctions ou d'opérations de table
  • Conservation des macros lorsque la requête est convertie au format strict. Les appels de macro sont remplacés par les expressions correspondantes et les définitions de macro sont supprimées.