Informationen zur MQL-Sprache

Auf dieser Seite finden Sie allgemeine Informationen zur MQL (Monitoring Query Language), einschließlich folgender Themen:

Diese Informationen gelten unabhängig davon, ob Sie MQL über die Google Cloud Console oder die Cloud Monitoring API verwenden. Informationen zur Struktur von MQL-Abfragen finden Sie unter Beispiele.

Tastenkombinationen für Tabellenvorgänge und -Funktionen

Abfragen bestehen in der Regel aus verbundenen Ketten von Tabellenvorgängen, die durch Pipes (|) verbunden sind. Diese beginnen mit dem Namen des Tabellenvorgangs, gefolgt von einer Liste mit Ausdrücken. Ausdrücke können Funktionsaufrufe enthalten, die ihre Argumente explizit auflisten. Die Monitoring-Abfragesprache ermöglicht es, Abfragen mit verschiedenen Tastenkombinationen auszudrücken.

In diesem Abschnitt werden Tastenkombinationen für Tabellenvorgänge, Funktionen als Tabellenvorgänge und eine Tastenkombination für Wertspalten als Argumente für Funktionen beschrieben.

Eine vollständige Liste finden Sie unter Tastenkombinationen für Tabellenvorgänge.

Tastenkombinationen für Tabellenvorgänge

Wenn Sie die Vorgänge fetch, group_by und filter verwenden, können Sie den expliziten Tabellenvorgang weglassen, wenn die Argumente für die Bestimmung des gewünschten Vorgangs ausreichen. Zum Beispiel die folgende Abfrage:

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

entspricht:

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

Die folgenden group_by-Vorgänge sind äquivalent:

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

Sie können das Wort filter weglassen, wenn Sie den Filtertest in Klammern setzen. Die folgenden beiden filter-Vorgänge sind beispielsweise äquivalent:

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

Sie können diese Tastenkombinationsformen in Ihren Abfragen kombinieren. Zum Beispiel die folgende Abfrage:

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

entspricht dieser expliziteren Form:

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

Weitere Informationen zu Tastenkombinationen für Tabellenvorgänge finden Sie in der MQL-Referenz unter Tastenkombinationen für Tabellenvorgänge.

Eine Funktion als Tabellenvorgang verwenden

Tabellenvorgänge beginnen in der Regel mit dem Namen eines Tabellenvorgangs. MQL ermöglicht es, Tabellenvorgänge stattdessen mit einem Funktionsnamen zu beginnen.

Sie können einen Funktionsnamen verwenden, wenn die benannte Funktion eine Transformation der Wertspalten der Eingabetabelle ausführen soll. Dieser Ersatz ist ein Kurzbefehl für die Tabellenvorgänge group_by, align oder value, je nach Art der Funktion, deren Name angegeben wird.

Die allgemeine Form ist:

|  FUNCTION_NAME ARG, ARG ... 

Während des Tabellenvorgangs verwendet die Funktion die Wertspalten der Eingabetabelle als Argumente, Argumente gefolgt von Argumenten für die Funktion selbst. Wenn Sie eine Funktion als Tabellenvorgang verwenden, geben Sie die Argumente in der Tabellenvorgangsform als kommagetrennte Liste an und nicht mit den umgebenden Klammern (()), die normalerweise bei Funktionen verwendet werden.

Der vollständige Tabellenvorgang, der durch Erweitern der Tastenkombination generiert wird, hängt von der Art der Funktion ab:

  • group_by: Wenn Sie eine aggregierende Funktion mit einem group_by-Vorgang verwenden, der alle Zeitachsenkennzeichnungs-Spalten wegaggregiert, d. h., wenn er [] zum Gruppieren verwendet, können Sie die Funktion als Tastenkombination verwenden. Beispiel:

    | distribution powers_of(1.1)

    ist eine Tastenkombination für

    | group_by [], distribution(val(0), powers_of(1.1))
  • align: Wenn Sie eine Ausrichtungsfunktion als Argument für den Vorgang align verwenden, können Sie die folgende Funktion als Tastenkombination verwenden. Beispiel:

    | delta

    ist eine Tastenkombination für

    | align delta()

    In ähnlicher Weise

    | rate 10m

    ist eine Tastenkombination für

    | align rate(10m)

    Beachten Sie, dass die Ausrichtungsfunktionen die Eingabezeitachsen als implizites Argument verwenden, sodass die Wertspalten hier nicht explizit angegeben werden.

  • value: Alle anderen Funktionen können als Tastenkombinationen für den Tabellenvorgang value dienen. Beispiel:

    | mul 3.3

    ist eine Tastenkombination für

    | value mul(val(0), 3.3)

    In ähnlicher Weise

    | div

    ist eine Tastenkombination für

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

    Die div-Tastenkombination verknüpft einen Eingabetabellenvorgang mit zwei Wertspalten und erzeugt einen Tabellenvorgang mit einer Wertespalte, die das Verhältnis darstellt.

Tastenkombination für Wertspaltenfunktionen

Sie können .function als Tastenkombination für function(val()) verwenden, wenn die Eingabe eine einzelne Wertspalte enthält, oder als Tastenkombination für function(val(0), val(1)), wenn es zwei Wertspalten gibt usw.

Der führende Punkt bedeutet: „Rufen Sie die folgende Funktion auf und geben Sie die Eingabepunktwertespalte(n) als Argument an die Funktion an.“

Beispielsweise ist .mean eine Tastenkombination für mean(val()). Folgendes ist äquivalent:

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

Wenn die Eingabetabelle mehrere Wertspalten enthält, wird jede Spalte zu einem Argument für die Funktion in diesem Kurzbefehl. Beispiel: Wenn die Eingabetabelle zwei Wertspalten enthält,

.div

ist eine Tastenkombination für

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

Mit diesem Kurzbefehl können Sie Argumente angeben, die nicht auf Wertspalten verweisen. Zusätzliche Argumente werden nach den Wertspaltenargumenten angegeben. Beispiel: Wenn die Eingabetabelle eine Wertspalte enthält,

.div(3)

entspricht

div(val(0), 3)

Variationen eines fetch

Der Vorgang fetch gibt in der Regel eine Zeitachsentabelle zurück, die nach einem Paar aus überwachtem Ressourcentyp und Messwerttyp benannt ist. Beispiel:

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

Gilt der Messwert nur für einen überwachten Ressourcentyp, können Sie die überwachte Ressource aus der Abfrage weglassen. Folgende Abfrage entspricht der vorherigen Abfrage, da der Messwert zur CPU-Auslastung nur für die überwachten gce_instance-Ressourcen gilt:

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

Der Vorgang fetch kann nur überwachte Ressourcentypen angeben, wobei der Messwert in einem nachfolgenden metric-Vorgang angegeben wird. Dieses Beispiel entspricht den vorherigen fetch-Beispielen:

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

Ein solches Aufteilen des fetch kann nützlich sein, wenn Sie zwei verschiedene Messwerte für dieselbe überwachte Ressource abrufen möchten. Beispiel: Folgende Abfrage berechnet die Anzahl von Paketen pro CPU-Sekunde:

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

Durch Aufteilen von fetch kann auch die Filterung nur auf die Labels der überwachten Ressource angewendet werden:

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

Auf einen fetch, der nur einen überwachten Ressourcentyp angibt, muss ein metric-Vorgang folgen, möglicherweise in Verbindung mit eingreifenden filter-Vorgängen.

Strict-Form-Abfragen

Eine Strict-Abfrage ist eine Abfrage ohne Tastenkombination oder implizite Werte, die in kurzen Abfragen verwendet werden. Strikte Abfragen haben folgende Eigenschaften:

  • Alle Tastenkombinationen werden ersetzt.
  • Alle impliziten Argumente werden explizit gemacht.
  • Spalten werden durch vollständige Namen referenziert.
  • Neuen Spalten werden explizit Namen gegeben.
  • Alle implizit bereitgestellten Ausrichtungsvorgänge werden explizit angegeben.

Die Verwendung der strikten Form macht die Abfrage widerstandsfähiger gegenüber Änderungen in der Struktur von Eingabetabellen, und es kann klarer werden, was die Abfrage tut. Eine Abfrage in strenger Form macht die Abfrage nicht effizienter.

Wenn Sie eine Abfrage für ein Diagramm speichern, wird sie in Strict-Form umgewandelt. Das Bestätigungsdialogfeld zum Speichern zeigt die Strict-Form an.

Prägnante Abfragen für Benachrichtigungsrichtlinien werden nicht in Strict-Form umgewandelt. Abfragen für Benachrichtigungsrichtlinien werden bei deren Bereitstellung gespeichert. Verwenden Sie entweder prägnante oder strikte Form.

Da beide Tastenkombinationen und strikte Formen verfügbar sind, können gleichwertige MQL-Abfragen auftreten, die sich sehr voneinander unterscheiden. Beispiel: Die folgende Abfrage, die die Anzahl der empfangenen Pakete pro verbrauchter CPU-Sekunde berechnet, verwendet viele Kurzbefehle:

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

Wenn Sie diese Abfrage in einem Diagramm oder als Teil einer Benachrichtigungsrichtlinie speichern, bewirkt die daraus resultierende strikte Form genau dasselbe. Das strikte Form kann jedoch anders aussehen, wie im folgenden Beispiel gezeigt:

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)]

Wenn Sie die gespeicherte Definition des Diagramms bearbeiten, zeigt der Code-Editor die strikte Form an.

Entspricht der Spalte resource.project_id.

Google Cloud-Projekte haben einen Anzeigenamen, der in Menüs angezeigt wird, aber das Projekt nicht eindeutig identifiziert. Der Anzeigename eines Projekts könnte „Monitoring-Demo“ lauten.

Weiter haben Projekte zwei Felder, die als Kennungen dienen:

  • Projekt-ID: eine eindeutige String-Kennung. Diese basiert häufig auf dem Anzeigenamen. Projekt-IDs werden beim Erstellen des Projekts festgelegt, in der Regel durch Verketten der Elemente des Projektnamens und eventuell weiterer Ziffern am Ende, wenn für die Eindeutigkeit notwendig. Eine Projekt-ID könnte etwa die Form "monitoring-demo" oder "monitoring-demo-2349" haben. Die Projekt-ID wird manchmal beiläufig als Projektname bezeichnet.
  • Projektnummer: Eine eindeutige numerische Kennung.

Jeder überwachte Ressourcentyp enthält ein project_id-Label mit einer Stringdarstellung der Projektnummer des Projekts, zu dem die Ressource gehört, und Daten zu dieser Ressource.

In MQL-Abfragen verweisen Sie auf dieses Label als resource.project_id. Das Label resource.project_id hat die Projektnummer in Textform als Wert, aber MQL wandelt diesen Wert in bestimmten Situationen in den Projekt-ID um.

In folgenden Fällen behandelt MQL den Wert des resource.project_id-Labels als Projekt-ID und nicht als Projektnummer:

  • Die Legende für ein Diagramm zeigt die Projekt-ID und nicht die Projektnummer für den Wert des resource.project_id-Labels.

  • Gleichheitsvergleiche des Werts der resource.project_id zu einem Stringliteral erkennen sowohl die Projektnummer als auch die Projekt-ID. Beispielsweise wird für beide Ressourcen, die diesem Projekt gehören, Folgendes zurückgegeben:

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

    Dieser Fall ist für die Operatoren == und != und für ihre Funktionsformen eq() und ne() relevant.

  • Der Abgleich mit regulären Ausdrücken gegen das resource.project_id-Label funktioniert sowohl mit der Projektnummer als auch mit der Projekt-ID korrekt. Beispiel: Beide der folgenden Ausdrücke können true für Ressourcen zurückgeben, die diesem Projekt gehören:

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

    Dieser Fall ist für die Operatoren =~ und !~ und für das Funktionsformular re_full_match relevant.

In allen anderen Fällen wird der tatsächliche Wert des resource.project_id-Labels verwendet. concatenate("project-", resource.project_id) ergibt beispielsweise den Wert project-530310927541 und nicht project-monitoring-demo.

Verhältnisse und „Edge-Effekt“

Im Allgemeinen ist es am besten, Verhältnisse basierend auf Zeitachsen zu berechnen, die unter Einsatz von Labelwerten für einen einzelnen Messwerttyp erfasst wurden. Ein Verhältnis, das über zwei verschiedene Messwerttypen berechnet wird, kann aufgrund unterschiedlicher Stichprobenzeiträume und Ausrichtungsfenster Anomalien verursachen.

Angenommen, Sie haben zwei verschiedene Messwerttypen, eine RPCs-Gesamtzahl und eine RPC-Fehlerzahl, und Sie möchten das Verhältnis von Fehler- zu Gesamtzahl berechnen. Die fehlgeschlagenen RPCs werden in der Zeitreihe beider Messwerttypen gezählt. Daher ist es möglich, dass beim Ausrichten der Zeitachse ein fehlgeschlagener RPC nicht für beide Zeitachsen im selben Ausrichtungsintervall erscheint. Dies kann folgende Gründe haben:

  • Da zwei verschiedene Zeitachsen dasselbe Ereignis aufzeichnen, gibt es zwei unterliegende Zählerwerte, die die Sammlung implementieren. Diese werden nicht atomar aktualisiert.
  • Die Abtastraten können abweichen. Wenn die Zeitachsen auf einen gemeinsamen Zeitraum ausgerichtet sind, kann die Anzahl für ein einzelnes Ereignis in angrenzenden Ausrichtungsintervallen für die verschiedenen Messwerte angezeigt werden.

Die unterschiedliche Anzahl der Werte in den entsprechenden Ausrichtungsintervallen kann zu einem unsinnigen error/total-Verhältniswert führen, z. B. 1/0 oder 2/1.

Verhältnisse größerer Zahlen führen mit geringerer Wahrscheinlichkeit zu unsinnigen Werten. Sie können größere Zahlen durch Aggregation erhalten, indem Sie entweder ein Ausrichtungsfenster verwenden, das länger als der Stichprobenzeitraum ist, oder indem Sie Daten für bestimmte Labels gruppieren. Diese Techniken minimieren den Effekt kleiner Unterschiede in der Anzahl der Punkte in einem gegebenen Intervall. Das heißt, ein Zwei-Punkte-Unterschied ist bei einer erwarteten Anzahl von 3 Punkten in einem Intervall signifikanter als bei einer erwarteten Anzahl von 300.

Wenn Sie integrierte Messwerttypen verwenden, haben Sie möglicherweise keine andere Wahl, als die Verhältnisse zwischen den Messwerttypen zu berechnen, um den von Ihnen benötigten Wert zu erhalten.

Wenn Sie benutzerdefinierte Messwerte entwerfen, die die gleiche Sache – wie RPCs, die den Fehlerstatus zurückgeben – in zwei verschiedenen Messwerten zählen könnten, sollten Sie stattdessen einen einzigen Messwert in Betracht ziehen, der jede Zählung nur einmal enthält. Angenommen, Sie zählen RPCs und möchten das Verhältnis von nicht erfolgreichen RPCs zu allen RPCs verfolgen. Zur Behebung dieses Problems erstellen Sie einen einzelnen Messwerttyp, um RPCs zu zählen, und verwenden ein Label, um den Status des Aufrufs einschließlich des Status „OK“ aufzuzeichnen. Dann wird jeder Statuswert bzw. jeder Fehler oder jedes „OK“ aufgezeichnet, indem für diesen Fall ein einzelner Zähler aktualisiert wird.

MQL-Datumsformate

MQL unterstützt derzeit nur eine begrenzte Anzahl an Datumsformaten. In MQL-Abfragen werden Datumsangaben auf folgende Arten dargestellt:

  • d'BASE_STRING'
  • D'BASE_STRING'

BASE_STRING ist ein String der Form 2010/06/23-19:32:15-07:00. Der erste Bindestrich (-) zwischen Datum und Uhrzeit kann durch ein Leerzeichen ersetzt werden. In der Zeitkomponente können Teile der Uhrzeit (19:32:15) oder der Zeitzonenspezifizierer (-07:00) weggelassen werden.

Folgende Beispiele sind gültige Datumsangaben in MQL-Abfragen:

  • 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'

Folgende Tabelle listet die Grammatik für den BASE_STRING auf:

Struktur Bedeutung
%Y/%m/%d Datum
%Y/%m/%d %H
%Y/%m/%d-%H
Datum, Stunde
%Y/%m/%d %H:%M
%Y/%m/%d-%H:%M
Datum, Stunde, Minute
%Y/%m/%d %H:%M:%S
%Y/%m/%d-%H:%M:%S
Datum, Stunde, Minute, Sekunde
%Y/%m/%d %H:%M:%E*S
%Y/%m/%d-%H:%M:%E*S
Datum, Stunde, Minute, Sekundenbruchteil
%Y/%m/%d %Ez Datum mit Zeitzone
%Y/%m/%d %H%Ez
%Y/%m/%d-%H%Ez
Datum, Stunde, mit Zeitzone
%Y/%m/%d %H:%M%Ez
%Y/%m/%d-%H:%M%Ez
Datum, Stunde, Minute, mit Zeitzone
%Y/%m/%d %H:%M:%S%Ez
%Y/%m/%d-%H:%M:%S%Ez
Datum, Stunde, Minute, Sekunde mit Zeitzone
%Y/%m/%d %H:%M:%E*S%Ez
%Y/%m/%d-%H:%M:%E*S%Ez
Datum, Stunde, Minute, Bruchsekunde, mit Zeitzone

Länge und Komplexität von Abfragen

Monitoring Query Language-Abfragen können lang und komplex sein, jedoch nicht ohne Grenzen.

  • UTF-8-codierte Abfragetexte sind auf 10.000 Byte beschränkt.
  • Eine Abfrage ist auf 2.000 Sprachkonstrukte beschränkt, d. h., die AST-Komplexität ist auf 2.000 Knoten beschränkt.

Eine abstrakte Syntaxstruktur (auch AST) ist eine Darstellung von Quellcode – in diesem Fall der MQL-Abfragestring – in der die Knoten in der Struktur zu syntaktischen Strukturen im Code zugeordnet werden.

MQL-Makros

MQL enthält ein Makrodefinitionsdienstprogramm. Sie können die MQL-Makros verwenden, um wiederkehrende Vorgänge zu ersetzen, komplexe Abfragen lesbarer zu machen und die Abfrageentwicklung zu vereinfachen. Sie können Makros für Tabellenvorgänge und Funktionen definieren.

Makrodefinitionen beginnen mit dem Schlüsselwort def.

Wenn Sie eine Abfrage in Strict-Form konvertieren, werden Makroaufrufe durch den entsprechenden Text ersetzt und die Makrodefinitionen werden entfernt.

Wenn Sie eine Diagrammabfrage mit Makros speichern, wird die Abfrage in Strict-Form umgewandelt, sodass keine Makros beibehalten werden. Wenn Sie eine Abfrage für eine Bedingung in einer Benachrichtigungsrichtlinie speichern, wird die Abfrage nicht in Strict-Form umgewandelt, sodass Makros beibehalten werden.

Makros für Tabellenvorgänge

Sie können Makros schreiben, um neue Tabellenvorgänge auszuführen. Die allgemeine Syntax sieht so aus:

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

Verwenden Sie folgende Syntax, um das Makro aufzurufen:

@MACRO_NAME [MACRO_ARG [, MACRO_ARG]]

Angenommen, Sie verwenden folgende Abfrage, um CPU-Auslastungsdaten abzurufen:

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

Die erste Zeile kann durch folgendes Makro ersetzt werden:

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

Zum Aufrufen des Makros in der Abfrage ersetzen Sie das ursprüngliche fetch so:

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

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

Sie können die zweite und dritte Zeile durch Makros ersetzen, die Argumente verwenden. Die Makrodefinition listet die Parameter für das Makro auf und verweisen im Makrotext auf die Parameter für das Makro als $MACRO_PARAMETER. Sie können zum Beispiel die folgenden Makros definieren:

def my_every time_arg = every $time_arg ;

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

Wenn Sie diese Makros aufrufen und Argumente bereitstellen möchten, geben Sie die Argumente in einer durch Kommas getrennten Liste in den Makroaufrufen an. Im Folgenden sehen Sie die Abfrage mit allen definierten Makros und deren Aufrufen:

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())

Makros werden nicht beibehalten, wenn die Abfrage in Strict-Form konvertiert wird. Die Strict-Form der vorherigen Abfrage sieht beispielsweise so aus:

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

Makros für Funktionen

Für MQL-Funktionen geben Sie Parameter in einer durch Kommas getrennten Liste in Klammern an. Die Klammern unterscheiden ein Funktionsmakro von einem Tabellenvorgangs-Makro. Die Klammer muss im Aufruf enthalten sein, auch wenn keine Argumente vorhanden sind. Makros werden nicht beibehalten, wenn die Abfrage in die strikte Form konvertiert wird.

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

Beispielsweise ruft die folgende Abfrage Tabellen für zwei Messwerte ab, kombiniert die beiden Tabellen zu einer mit zwei Wertespalten und berechnet das Verhältnis der empfangenen Bytes zu den Gesamtbytes für eine Spalte namens 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))]

Sie können die received_percent-Berechnung durch ein Makro ersetzen, wie im folgenden Beispiel gezeigt:

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

Verwenden Sie folgende Syntax, um ein Funktions-Makro aufzurufen:

@MACRO_NAME([MACRO_ARG[, MACRO_ARG]])

Wird ein Funktions-Makro ohne Argumente aufgerufen, müssen Sie die leeren Klammern angeben, um den Aufruf vom Aufruf eines Tabellenvorgangs-Makros zu unterscheiden.

Folgendes Beispiel zeigt die vorherige Abfrage mit einem Makro zur Verhältnisberechnung:

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))]

Funktionen von Makros

MQL-Makros sind syntaktische Elemente, im Gegensatz zu Textelementen wie den im C-Präprozessor verwendeten Makros. Diese Unterscheidung bedeutet, dass ein MQL-Makrotext immer ein syntaktisch gültiger Ausdruck sein muss. Sie ist möglicherweise semantisch nicht gültig, was auch von den Makroargumenten und dem Standort abhängt, an dem das Makro erweitert ist.

Da MQL-Makros syntaktisch sind, gibt es nur wenige Einschränkungen für die Art von Ausdruck, auf die sie erweitert werden können. Syntaxmakros sind nur eine weitere Möglichkeit, die abstrakte Syntaxstruktur zu bearbeiten. Die folgenden Beispiele zeigen einige Möglichkeiten, die Sie mit syntaktischen Makros tun können:

# 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 unterstützt auch die implizite String-Literal-Verkettung. Diese Funktion kann beim Schreiben von Abfragen, die lange Messwertnamen enthalten, sehr nützlich sein. Wenn ein Stringliteral und ein Makroargument, das auch ein Stringliteral sein muss, neben dem Makrotext stehen, werden sie zu einem einzelnen Stringliteral verkettet.

Im folgenden Beispiel ist gce_instance ein lexikalisches BARE_NAME-Element. Es wird automatisch zu einem String-Literal hochgestuft, das beim Erstellen von Tabellennamen hilfreich ist:

# 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);

Als Zusammenfassung verwendet die folgende Abfrage alle zuvor definierten Makros:

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

Makroargumente können auch beliebige Ausdrücke sein, solange sie syntaktisch korrekt sind. Das Makro my_filter kann beispielsweise einen booleschen Ausdruck wie instance_name =~ 'gke.*' als erstes Argument verwenden.

Das Abkürzen von Tabellenvorgängen kann ebenfalls sehr nützlich sein, wie die folgende Abfrage zeigt:

# 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]

Funktions-Makros können sich wie reguläre Funktionen verhalten. Das heißt, sie ermöglichen die Hochstufung von Funktionen, wobei die Wertspalte oder -spalten der Eingabetabelle die ersten Argumente für das Makro werden. Das folgende Beispiel zeigt eine Variante der vorherigen Abfrage, die ein Funktions-Makro verwendet:

# 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]

Beschränkungen

Das MQL-Makrofeature unterstützt Folgendes nicht:

  • Verschachtelung von Makrodefinitionen: Sie können ein Makro nicht im Text eines anderen Makros definieren.
  • Rekursiv definierte Makros. Kein Makrotext kann auf ein Makro verweisen, auch nicht auf sich selbst, das noch nicht vollständig definiert ist.
  • Verwendung von makrodefinierten Funktionen als Tabellenvorgänge.
  • Verwendung von Makroargumenten als Namen von Funktionen oder Tabellenvorgängen.
  • Beibehaltung von Makros, wenn die Abfrage in Strict-Form umgewandelt wird. Die Makroaufrufe werden durch die entsprechenden Ausdrücke ersetzt und die Makrodefinitionen werden entfernt.