Esta página foi traduzida pela API Cloud Translation.
Switch to English

Sobre a linguagem MQL

Esta página fornece informações gerais sobre a linguagem de consulta de monitoramento (MQL, na sigla em inglês), incluindo os seguintes tópicos:

Essas informações se aplicam se você usa a MQL no Console do Google Cloud ou na API Cloud Monitoring. Para informações sobre a estrutura das consultas da MQL, consulte Exemplos.

Atalhos para funções e operações de tabela

As consultas geralmente consistem em redes de operações de tabela conectadas por barras verticais (|), e cada uma delas começa com o nome da operação da tabela seguido de uma lista de expressões. As expressões podem conter chamadas de função que listam todos os argumentos explicitamente. Entretanto, a MQL permite que as consultas sejam expressas com vários atalhos.

Nesta seção, descrevemos os atalhos para operações de tabela, como usar funções como operações de tabela e um atalho para colunas de valor como argumentos de funções.

Para ver uma lista completa, consulte Atalhos de operação de tabela.

Atalhos para operações de tabela

Ao usar as operações fetch, group_by e filter, é possível omitir a operação de tabela explícita quando os argumentos forem suficientes para determinar a operação pretendida. Por exemplo, a consulta a seguir:

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

é equivalente a:

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

As seguintes operações group_by são equivalentes:

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

É possível omitir a palavra filter se o teste de filtro for colocado entre parênteses. Por exemplo, as duas operações filter a seguir são equivalentes:

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

É possível combinar esses formulários de atalho nas consultas. Por exemplo, a consulta a seguir:

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

é equivalente a esta forma mais explícita:

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

Para mais informações sobre atalhos de operações de tabela, consulte Atalhos de operação de tabela na referência da MQL.

Como usar uma função como uma operação de tabela

Uma operação de tabela geralmente começa com o nome de uma operação de tabela. Entretanto, a MQL permite que uma operação de tabela comece com um nome de função.

É possível usar um nome de função quando a função executará uma transformação das colunas de valor da tabela de entrada. Essa substituição é um atalho para as operações de tabela group_by, align ou value, dependendo do tipo de função que recebeu um nome.

O formato geral é:

|  FUNCTION_NAME ARG, ARG ... 

Na operação de tabela, a função usa as colunas de valor da tabela de entrada como argumentos e os argumentos seguidos por qualquer argumento para a própria função. Ao usar uma função como uma operação de tabela, você especifica os argumentos na forma de operação de tabela como uma lista separada por vírgulas, em vez de usar parênteses adjacentes (()) normalmente usados com funções.

A operação completa de tabela gerada pela expansão do atalho depende do tipo de função:

  • group_by: se você estiver usando uma função de agregação com uma operação group_by que agrega todas as colunas do identificador de série temporal (ou seja, [] para agrupamento) é possível usar a função como um atalho. Por exemplo:

    | distribution powers_of(1.1)

    é um atalho para

    | group_by [], distribution(val(0), powers_of(1.1))
  • align: se você estiver usando uma função de alinhamento como um argumento para a operação align, será possível usar a função como um atalho. Por exemplo:

    | delta

    é um atalho para

    | align delta()

    Da mesma forma,

    | rate 10m

    é um atalho para

    | align rate(10m)

    Observe que as funções de alinhador usam a série temporal de entrada como argumento implícito. Portanto, as colunas de valor não são fornecidas explicitamente nesse caso.

  • value: todas as outras funções podem funcionar como atalhos para a operação de tabela value. Por exemplo:

    | mul 3.3

    é um atalho para

    | value mul(val(0), 3.3)

    Da mesma forma,

    | div

    é um atalho para

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

    Observe que o atalho div cria uma operação de tabela de entrada com duas colunas de valor e produz uma operação de tabela com uma coluna de valor que é a proporção.

Atalho para funções de valor e coluna

É possível usar .function como atalho para function(val()) se houver uma única coluna de valor na entrada ou como atalho para function(val(0), val(1)) se houver duas colunas de valor, e assim por diante.

O ponto inicial significa: "Chame a seguinte função, fornecendo a coluna (ou colunas) de valor do ponto de entrada como o(s) argumento(s) para a função."

Por exemplo, .mean é um atalho para mean(val()). Os seguintes são equivalentes:

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

Se a tabela de entrada tiver várias colunas de valor, cada coluna se tornará um argumento para a função nesse atalho. Por exemplo, se a tabela de entrada tiver duas colunas de valor, então

.div

é um atalho para

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

Com esse atalho, é possível fornecer argumentos que não se referem a colunas de valor. Os argumentos extras são fornecidos depois dos argumentos da coluna de valor. Por exemplo, se a tabela de entrada tiver uma coluna de valor, então

.div(3)

é equivalente a

div(val(0), 3)

Variações em um fetch

A operação fetch geralmente retorna uma tabela de séries temporais denominadas por um par de tipos de métricas e recursos monitorados. Exemplo:

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

Se a métrica se aplicar apenas a um tipo de recurso monitorado, será possível omitir o recurso monitorado da consulta. A consulta a seguir é equivalente à consulta anterior, porque a métrica de utilização da CPU aplica-se apenas aos recursos monitorados gce_instance:

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

A operação fetch pode especificar apenas um tipo de recurso monitorado, com a métrica especificada em operações metric subsequentes. Este exemplo é equivalente aos exemplos de fetch anteriores:

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

Dividir a fetch dessa maneira pode ser útil quando você quiser buscar duas métricas diferentes para o mesmo recurso monitorado. Por exemplo, a consulta a seguir calcula o número de pacotes por segundo de CPU consumidos:

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

Dividir fetch também permite aplicar a filtragem apenas aos rótulos do recurso monitorado:

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

Uma fetch que denomina apenas um tipo de recurso monitorado precisa ser seguida por uma operação metric, talvez com operações filter intermediárias.

Consultas de formato restrito

Uma consulta restrita é aquela sem atalhos nem valores implícitos:

  • Todos os atalhos foram substituídos.
  • Todos os argumentos implícitos são explícitos.
  • As colunas são referenciadas por nomes completos.
  • Novas colunas recebem nomes explicitamente.
  • Todas as operações de alinhamento fornecidas implicitamente são fornecidas explicitamente.

O uso do formato restrito torna a consulta mais resiliente a mudanças na estrutura das tabelas de entrada e pode deixar mais claro o que a consulta está fazendo. Usar uma consulta de formato restrito não torna a consulta mais eficiente.

Quando você salva uma consulta para um gráfico ou uma política de alertas, ela é convertida para o formato estrito. A caixa de diálogo de confirmação da operação de salvamento exibe o formato restrito.

Com atalhos e formatos restritos disponíveis, é possível encontrar consultas MQL equivalentes que são muito diferentes umas das outras. Por exemplo, a consulta a seguir, que calcula o número de pacotes recebidos por segundo de CPU consumida, usa muitos atalhos:

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

Quando você salva essa consulta em um gráfico ou como parte de uma política de alertas, a consulta de formato restrito faz exatamente a mesma coisa. No entanto, o formato restrito pode ser muito diferente, conforme mostrado no exemplo a seguir:

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

Quando você edita a definição salva do gráfico ou da política de alertas, o "Editor de consultas" exibe o formato restrito.

Como fazer a correspondência com a coluna resource.project_id

Os projetos do Google Cloud têm um nome de exibição que aparece nos menus, mas não identifica exclusivamente o projeto. O nome de exibição do projeto pode ser "Demonstração do Monitoring".

Os projetos também têm dois campos que atuam como identificadores:

  • ID do projeto: um identificador exclusivo da string. Ele geralmente é baseado no nome de exibição. Os IDs do projeto são definidos quando o projeto é criado, geralmente concatenando os elementos do nome do projeto e possivelmente adicionando números ao final, se necessário para gerar exclusividade. Um ID do projeto pode ter o formato "monitoring-demo" ou "monitoring-demo-2349". O ID do projeto às vezes é chamado de "nome do projeto".
  • Número do projeto: um identificador numérico exclusivo.

Cada tipo de recurso monitorado inclui um rótulo project_id com uma representação de string do número do projeto que é proprietário do recurso e dos dados desse recurso.

Nas consultas MQL, esse rótulo é chamado de resource.project_id. O rótulo resource.project_id tem o número do projeto em forma de texto como o valor, mas a MQL converte esse valor ao ID do projeto em determinadas situações.

Nos casos a seguir, a MQL trata o valor do rótulo resource.project_id como o ID do projeto em vez de número do projeto:

  • A legenda de um gráfico exibe o ID do projeto em vez do número do projeto para o valor do rótulo resource.project_id.

  • As comparações de igualdade de valor de resource.project_id com um literal de string reconhecem tanto o número quanto o ID do projeto. Por exemplo, os seguintes itens retornam "true" para os recursos que pertencem a este projeto:

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

    Esse caso se aplica aos operadores == e != e aos formatos de função eq() e ne().

  • Uma correspondência de expressão regular no rótulo resource.project_id funciona corretamente no número ou no ID do projeto. Por exemplo, as duas expressões a seguir retornam true para recursos pertencentes a esse projeto:

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

    Esse caso se aplica aos operadores =~ e !~ e ao formato de função re_full_match.

Para todos os outros casos, o valor real do rótulo resource.project_id é usado. Por exemplo, concatenate("project-", resource.project_id) resulta no valor project-530310927541, e não em project-monitoring-demo.

Proporções e o "efeito de borda"

Em geral, é melhor calcular proporções com base em séries temporais coletadas para um único tipo de métrica usando valores de rótulo. Uma proporção calculada em dois tipos diferentes de métricas está sujeita a um efeito de borda.

Por exemplo, suponha que você tem dois tipos de métrica diferentes, uma contagem total de RPC e uma contagem de erros de RPC, e quer calcular a proporção de contagem de erros de RPC em relação ao total de RPCs. As RPCs sem sucesso são contadas em séries temporais de ambos os tipos de métrica. Assim, quando você alinha as séries temporais, uma RPC sem sucesso pode aparecer em um intervalo de alinhamento na contagem total, mas em um intervalo de alinhamento diferente na contagem de erros. Essa diferença pode ocorrer por vários motivos, incluindo:

  • Como há duas séries temporais diferentes gravando o mesmo evento, há dois valores de contador subjacentes implementando a coleta, e eles não serão atualizados atomicamente.
  • As taxas de amostragem podem ser diferentes. Quando as séries temporais estão alinhadas a um período comum, as contagens de um único evento podem aparecer em intervalos de alinhamento adjacentes na série temporal de diferentes métricas.

A diferença no número de valores nos intervalos de alinhamento correspondentes pode levar a valores de proporção error/total ilógicos, como 1/0 ou 2/1.

O efeito de borda é geralmente menor para proporções entre números maiores. É possível conseguir números maiores por agregação, seja usando uma janela de alinhamento maior que o período de amostragem ou agrupando dados para determinados rótulos. Essas técnicas minimizam o efeito de pequenas diferenças no número de pontos em um determinado intervalo. Uma disparidade de dois pontos é mais significativa se o número esperado de pontos em um intervalo for três do que se o número esperado for 300.

Se você estiver usando tipos de métricas integrados, talvez não tenha opção senão calcular proporções nos tipos de métricas para obter o valor necessário.

Se você estiver criando métricas personalizadas para contar o mesmo resultado (como RPCs que retornam status de erro) em duas métricas diferentes, considere uma única métrica que inclua cada contagem apenas uma vez. Por exemplo, se você estiver contando RPCs e quiser acompanhar a proporção de RPCs com falha para todos os RPCs, crie um único tipo de métrica para contar RPCs e use um rótulo para registrar o status da invocação, incluindo o status "OK". Depois, cada valor de status, de erro ou "OK" será registrado ao atualizar um contador único para esse caso.

Formatos de data da MQL

Atualmente, a MQL é compatível com um número limitado de formatos de data. Nas consultas de MQL, as datas são expressas como uma das seguintes opções:

  • d'BASE_STRING'
  • D'BASE_STRING'

A BASE_STRING é uma string no formato 2010/06/23-19:32:15-07:00. O primeiro traço (-), separando a data e a hora, pode ser substituído por um espaço. No componente de tempo, partes do horário do relógio (19:32:15) ou o especificador de fuso horário (-07:00) podem ser descartados.

Os exemplos a seguir são datas válidas nas consultas de 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'

A tabela a seguir lista a sintaxe de BASE_STRING:

Estrutura Significado
%Y/%m/%d Data
%Y/%m/%d %H
%Y/%m/%d-%H
Data e hora
%Y/%m/%d %H:%M
%Y/%m/%d-%H:%M
Data, hora e minuto
%Y/%m/%d %H:%M:%S
%Y/%m/%d-%H:%M:%S
Data, hora, minuto e segundo
%Y/%m/%d %H:%M:%E*S
%Y/%m/%d-%H:%M:%E*S
Data, hora, minuto e fração de segundo
%Y/%m/%d %Ez Data com fuso horário
%Y/%m/%d %H%Ez
%Y/%m/%d-%H%Ez
Data e hora, com fuso horário
%Y/%m/%d %H:%M%Ez
%Y/%m/%d-%H:%M%Ez
Data, hora e minuto, com fuso horário
%Y/%m/%d %H:%M:%S%Ez
%Y/%m/%d-%H:%M:%S%Ez
Data, hora, minuto e segundo, com fuso horário
%Y/%m/%d %H:%M:%E*S%Ez
%Y/%m/%d-%H:%M:%E*S%Ez
Data, hora, minuto e fração de segundo, com fuso horário

Comprimento e complexidade das consultas

As consultas da MQL podem ser longas e complexas, mas não ilimitadas.

  • Um texto de consulta, codificado como UTF-8, tem o limite de 10.000 bytes.
  • Uma consulta é limitada a 2.000 construções de idiomas. Ou seja, a complexidade do AST é limitada a 2.000 nós.

Uma árvore de sintaxe abstrata (AST na sigla em inglês) é uma representação do código-fonte (nesse caso, a string de consulta da MQL) em que nós no mapa são mapeadas para estruturas sintáticas no código.

Macros do MQL

O MQL inclui um utilitário de definição de macro, def. Use o utilitário de definição de macro MQL para substituir operações repetidas, facilitar a leitura de consultas complexas e facilitar o desenvolvimento de consultas. É possível definir macros para operações de tabela e funções.

Macros para operações de tabela

É possível escrever macros para criar novas operações de tabela. A sintaxe geral é semelhante a esta:

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

Para invocar a macro, use a seguinte sintaxe:

@MACRO_NAME [MACRO_ARG [, MACRO_ARG]]

Por exemplo, suponha que você esteja usando a seguinte consulta para buscar dados de utilização da CPU:

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

A primeira linha pode ser substituída pela seguinte macro:

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

Para invocar a macro na consulta, substitua o fetch original da seguinte maneira:

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

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

É possível substituir a segunda e a terceira linhas por macros que usam argumentos. A definição da macro lista os parâmetros dela e, no corpo da macro, consulte os parâmetros correspondentes como $MACRO_PARAMETER. Por exemplo, é possível definir as seguintes macros:

def my_every time_arg = every $time_arg ;

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

Para invocar essas macros e fornecer os argumentos, especifique os argumentos em uma lista delimitada por vírgulas nas invocações da macro. Veja a seguir a consulta com todas as macros definidas e as invocações:

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

Macros de funções

Para funções MQL, especifique quaisquer parâmetros em uma lista delimitada por vírgulas entre parênteses. Os parênteses diferenciam uma macro de função de uma macro de operação de tabela. O parêntese precisa aparecer na invocação, mesmo que não haja argumentos.

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

Por exemplo, a consulta a seguir recupera tabelas de duas métricas, combina as duas tabelas em uma com duas colunas de valor e calcula a proporção de bytes recebidos para o total de bytes de uma coluna chamada 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))]

É possível substituir o cálculo received_percent por uma macro como no exemplo a seguir:

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

Para invocar uma macro de função, use esta sintaxe:

@MACRO_NAME([MACRO_ARG[, MACRO_ARG]])

Ao invocar uma macro de função sem argumentos, você precisa especificar os parênteses vazios para distinguir a invocação da invocação de uma macro de operação de tabela.

O exemplo a seguir mostra a consulta anterior com uma macro para o cálculo da proporção:

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

Limitações

O recurso de macro MQL não é compatível com o seguinte:

  • Aninhamento de macros.
  • Macros definidas de modo recursivo. Nenhum corpo de macro pode referenciar qualquer macro, inclusive ela mesma, que ainda não tenha sido totalmente definida.
  • Uso de funções definidas por macros como operações de tabela.
  • Uso de argumentos de macro como nomes de funções ou operações de tabela.