Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Acerca del lenguaje de consultas de Monitoring (MQL)

Esta página proporciona información general sobre el lenguaje de consulta de Monitoring (MQL), incluidos los siguientes temas:

Esta información se aplica si usas MQL desde Google Cloud Console o desde la API de Cloud Monitoring. Para obtener información sobre la estructura de consultas de GQL, consulta Ejemplos.

Combinaciones de teclas para las operaciones y operaciones de tablas

Por lo general, las consultas constan de cadenas conectadas de operaciones de tabla conectadas por pipes (|), cada una de las cuales comienza con el nombre de la operación de tabla seguida de una lista de expresiones. Las expresiones pueden contener llamadas a funciones que enumeran todos sus argumentos de forma explícita. Pero el lenguaje de consulta de Monitoring permite que las consultas se expresen con una variedad de accesos directos.

En esta sección, se describen las combinaciones de teclas para las operaciones de tabla, el uso de funciones como operaciones de tabla y un acceso directo para las columnas de valores como argumentos de las funciones.

Para obtener una lista completa, consulta Combinaciones de teclas de operaciones de tablas.

Combinaciones de teclas para las operaciones de tabla

Cuando se usan las operaciones fetch, group_by y filter, puedes omitir la operación explícita de la tabla cuando los argumentos son suficientes para determinar la operación prevista. Por ejemplo, la siguiente consulta:

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

es equivalente a lo siguiente:

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

Las siguientes operaciones group_by son equivalentes:

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

Puedes omitir la palabra filter si calificas la prueba de filtro. Por ejemplo, las dos operaciones filter siguientes son equivalentes:

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

Puedes combinar estos formularios de accesos directos en tus consultas. Por ejemplo, la siguiente consulta:

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

es equivalente a este formulario más explícito:

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

Si deseas obtener más información sobre los accesos directos para las operaciones de tablas, consulta Combinaciones de teclas para operaciones de tablas en la referencia de MQL.

Usa una función como operación de tabla

Por lo general, una operación de tabla comienza con el nombre de una operación de tabla. Pero MQL permite que una operación de tabla comience con el nombre de una función en su lugar.

Puedes usar un nombre de función cuando la función con nombre es realizar una transformación de las columnas de valor de la tabla de entrada. Este reemplazo es un acceso directo para las operaciones de la tabla group_by, align o value, según el tipo de función con un nombre determinado.

El formato general es el siguiente:

|  FUNCTION_NAME ARG, ARG ... 

En la operación de tabla, la función toma las columnas de valor de la tabla de entrada como argumentos, argumentos seguidos de cualquier argumento para la función en sí. Cuando se usa una función como una operación de tabla, debes especificar los argumentos en el formulario de operación de tabla, como una lista separada por comas, en lugar de los paréntesis que se encuentran entre sí (()) normalmente usados con las funciones.

La operación completa de la tabla generada mediante la expansión del acceso directo depende de la clase de función:

  • group_by: Si estás usando unfunción de agregación con ungroup_by operación que agrega todas las columnas de identificador de serie temporal (es decir, usa[] para agrupar), puedes usar la función como acceso directo. Por ejemplo:

    | distribution powers_of(1.1)

    es un acceso directo para

    | group_by [], distribution(val(0), powers_of(1.1))
  • align: Si usas una función de alineación como argumento para la operación align, puedes usar la función como acceso directo. Por ejemplo:

    | delta

    es un acceso directo para

    | align delta()

    Del mismo modo

    | rate 10m

    es un acceso directo para

    | align rate(10m)

    Ten en cuenta que las funciones de alineador toman la serie temporal de entrada como un argumento implícito, por lo que las columnas de valor no se proporcionan de manera explícita aquí.

  • value: Todas las demás funciones pueden actuar como accesos directos para la operación de tabla value. Por ejemplo:

    | mul 3.3

    es un acceso directo para

    | value mul(val(0), 3.3)

    Del mismo modo

    | div

    es un acceso directo para

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

    Ten en cuenta que la combinación de teclas div permite una operación de tabla de entrada con dos columnas de valores y produce una operación de tabla con una columna de valores que es la proporción.

Acceso directo para funciones de columna-valor

Puedes usar .function como acceso directo para function(val()) si hay una sola columna de valor en la entrada o como acceso directo a function(val(0), val(1)) si hay dos valores. columnas, entre otras.

El punto al principio significa "Llamar a la siguiente función, proporcionando la columna de valor de punto de entrada (o columnas) como argumentos para la función".

Por ejemplo, .mean es un acceso directo para mean(val()). Los siguientes son equivalentes:

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

Si la tabla de entrada tiene varias columnas de valores, cada columna se convierte en un argumento para la función en este acceso directo. Por ejemplo, si la tabla de entrada tiene dos columnas de valores, entonces

.div

es un acceso directo para

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

Con esta combinación de teclas, puedes proporcionar argumentos que no hagan referencia a las columnas de valor. Los argumentos adicionales se proporcionan después de los argumentos de columna-valor. Por ejemplo, si la tabla de entrada tiene una columna de valores, la

.div(3)

es equivalente a

div(val(0), 3)

Variaciones en fetch

Por lo general, la operación fetch muestra una tabla de series temporales con el nombre de un par de tipos de métricas y recursos supervisados. Por ejemplo:

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

Si la métrica se aplica solo a un tipo de recurso supervisado, puedes omitir el recurso supervisado de la consulta. La siguiente consulta es equivalente a la consulta anterior, porque la métrica de uso de CPU solo se aplica a recursos supervisados gce_instance:

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

La operación fetch puede especificar solo un tipo de recurso supervisado, con la métrica especificada en operaciones metric posteriores. Por ejemplo, este ejemplo es equivalente a los ejemplos de fetch anteriores:

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

Dividir la fetch de esta manera puede ser útil cuando quieres recuperar dos métricas diferentes para el mismo recurso supervisado. Por ejemplo, la siguiente consulta calcula la cantidad de paquetes 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 también te permite aplicar filtrado solo a las etiquetas del recurso supervisado:

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

Una fetch que nombra solo un tipo de recurso supervisado debe estar seguida por una operación metric, tal vez con operaciones filter intercaladas.

Consultas estrictas

Una consulta estricta es una sin accesos directos o valores implícitos:

  • Se reemplazarán todas las combinaciones de teclas.
  • Todos los argumentos implícitos son explícitos.
  • Las columnas se denominan nombres completos.
  • Las columnas nuevas reciben nombres determinados de manera explícita.
  • Todas las operaciones de alineación proporcionadas de forma implícita se proporcionan de forma explícita.

El uso del formulario estricto hace que la consulta sea más resistente a los cambios en la estructura de las tablas de entrada, y puede aclarar mejor lo que hace la consulta. Escribir una consulta en forma estricta no hace que la consulta sea más eficiente.

Cuando guardas una consulta para un gráfico o una política de alertas, se convierte en forma estricta. El cuadro de diálogo de confirmación para la operación de guardado muestra la forma estricta.

Con tanto las combinaciones de teclas como las formas estrictas disponibles, es posible que encuentres consultas MQ equivalentes que se vean muy diferentes entre sí. Por ejemplo, en la siguiente consulta, que calcula la cantidad de paquetes recibidos por segundo de CPU consumida, usa muchas combinaciones de teclas:

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

Cuando guardas esta consulta en un gráfico o como parte de una política de alertas, la consulta de formulario estricta resultante hace lo mismo. Sin embargo, la forma estricta puede ser bastante diferente, como se muestra en el siguiente ejemplo:

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

Cuando editas la definición guardada del gráfico o la política de alertas, el Editor de consultas muestra la forma estricta.

Coincidencia con la columna resource.project_id

Los proyectos de Google Cloud tienen un nombre comercial, que aparece en menús, pero no identifica el proyecto de manera única. Un nombre visible del proyecto puede ser “Demostración de Monitoring”.

Los proyectos también tienen dos campos que actúan como identificadores:

  • ID del proyecto: un identificador de string único. Esto suele basarse en el nombre comercial. Los ID del proyecto se configuran cuando se crea el proyecto; en general, se concatenan los elementos del nombre del proyecto y se agregan dígitos al final, si es necesario. Un ID del proyecto puede tener la forma “monitoring-demo” o “monitoring-demo-2349”. En ocasiones, el ID del proyecto se denomina nombre del proyecto de forma informal.
  • Número de proyecto: un identificador numérico único.

Cada tipo de recurso supervisado incluye una etiqueta project_id, con una representación de string del número del proyecto que posee el recurso y los datos sobre ese recurso.

En las consultas de MQL, hace referencia a esta etiqueta como resource.project_id. La etiqueta resource.project_id tiene el número de proyecto en forma de texto como su valor, pero MQL convierte ese valor al ID del proyecto en algunas situaciones.

En los siguientes casos, MQL trata el valor de la etiqueta resource.project_id como el ID del proyecto en lugar del número del proyecto:

  • La leyenda de un gráfico muestra el ID del proyecto en lugar del número del proyecto para el valor de la etiqueta resource.project_id.

  • Las comparaciones de igualdad del valor de resource.project_id a un literal de string reconocen el número del proyecto y el ID del proyecto. Por ejemplo, lo siguiente muestra verdadero para los recursos que pertenecen a este proyecto:

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

    Este caso se aplica a los operadores == y !=, y para sus formas de funciones, eq() y ne().

  • Una coincidencia de expresión regular en la etiqueta resource.project_id funciona de manera correcta con el número de proyecto o con el ID del proyecto. Por ejemplo, las siguientes expresiones muestran true para los recursos que pertenecen a este proyecto:

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

    Este caso se aplica a los operadores =~ y !~, y para la forma de función, re_full_match.

En todos los demás casos, se usa el valor real de la etiqueta resource.project_id. Por ejemplo, concatenate("project-", resource.project_id) da como resultado el valor project-530310927541 y no project-monitoring-demo.

Relaciones y el "efecto perimetral"

En general, es mejor calcular las relaciones en función de series temporales recopiladas para un solo tipo de métrica mediante valores de etiquetas. Una proporción calculada en dos tipos de métricas diferentes está sujeta a un efecto perimetral.

Por ejemplo, supongamos que tienes dos tipos de métricas diferentes, un recuento total de RPC y un recuento de errores de RPC, y quieres calcular la proporción de RPC de recuento de errores en total de RPC. Las RPC no exitosas se cuentan en series temporales de ambos tipos de métrica. Es por esto que existe la posibilidad de que, cuando alinear la serie temporal, una RPC no exitosa aparezca en un intervalo de alineación en el conteo total. en un intervalo de alineación diferente para el conteo de errores. Esta diferencia puede deberse a varios motivos, incluidos los siguientes:

  • Debido a que hay dos series temporales diferentes que registran el mismo evento, hay dos valores de contador subyacentes que implementan la colección y no se actualizan de forma atómica.
  • Las tasas de muestreo pueden variar. Cuando las series temporales se alinean con un período común, los recuentos de un solo evento pueden aparecer en intervalos de alineación adyacentes en las series temporales de las diferentes métricas.

La diferencia en la cantidad de valores en los intervalos de alineación correspondientes puede dar lugar a valores de proporción error/total no sensibles, como 1/0 o 2/1.

El efecto de borde generalmente es menor para las relaciones entre números más altos. Puedes obtener números más grandes por agregación, ya sea mediante una ventana de alineación que sea más larga que el período de muestreo o agrupa datos para ciertas etiquetas. Estas técnicas minimizan el efecto de las pequeñas diferencias en la cantidad de puntos en un intervalo determinado; una disparidad de dos puntos es más significativo si la cantidad esperada de puntos en un intervalo es tres que si el número esperado es 300.

Si usas tipos de métricas integradas, es posible que no tengas más opción, además de calcular relaciones entre los tipos de métricas para obtener el valor que necesitas.

Si diseñas métricas personalizadas que pueden contar lo mismo, como RPC que muestran el estado de error, en dos métricas diferentes, considera, en cambio, una sola métrica, que incluye cada recuento solo una vez. Por ejemplo, si cuentas las RPC y deseas realizar un seguimiento de la proporción de RPC no exitosas en todas las RPC, crea un solo tipo de métrica para contar las RPC y usa una etiqueta para registrar el estado del invocación, incluido el estado “OK”. Luego, cada valor de estado, error o “OK” se registra mediante la actualización de un contador único para ese caso.

Formatos de fecha de MQL

Actualmente, MQL admite una cantidad limitada de formatos de fecha. En las consultas de MQL, las fechas se expresan como una de las siguientes opciones:

  • d'BASE_STRING'
  • D'BASE_STRING'

El BASE_STRING es una string del formulario 2010/06/23-19:32:15-07:00. El primer guion (-), que separa la fecha y hora, se puede reemplazar por un espacio. En el componente de hora, se pueden descartar partes del tiempo del reloj (19:32:15) o el especificador de zona horaria (-07:00).

Los siguientes ejemplos son fechas válidas en las 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'

En la siguiente tabla, se muestra la gramática de BASE_STRING:

Estructura Significado
%Y/%m/%d Date
%Y/%m/%d %H
%Y/%m/%d-%H
DATE, HOUR
%Y/%m/%d %H:%M
%Y/%m/%d-%H:%M
Fecha, hora, minuto
%Y/%m/%d %H:%M:%S
%Y/%m/%d-%H:%M:%S
Fecha, hora, minuto, segundo
%Y/%m/%d %H:%M:%E*S
%Y/%m/%d-%H:%M:%E*S
Fecha, hora, minuto, fracción fraccional
%Y/%m/%d %Ez Fecha con zona horaria
%Y/%m/%d %H%Ez
%Y/%m/%d-%H%Ez
Fecha, hora, con zona horaria
%Y/%m/%d %H:%M%Ez
%Y/%m/%d-%H:%M%Ez
Fecha, hora, minuto, con zona horaria
%Y/%m/%d %H:%M:%S%Ez
%Y/%m/%d-%H:%M:%S%Ez
Fecha, hora, minuto, segundo, con zona horaria
%Y/%m/%d %H:%M:%E*S%Ez
%Y/%m/%d-%H:%M:%E*S%Ez
Fecha, hora, minuto, fracción fraccionaria, con zona horaria

Longitud y complejidad de las consultas

La supervisión de las consultas del lenguaje de consulta puede ser extensa y compleja, pero no sin límites.

  • Un texto de consulta, codificado como UTF-8, se limita a 10,000 bytes.
  • Una consulta está limitada a 2,000 compilaciones de idiomas. es decir, la complejidad del AST está limitada a 2,000 nodos.

Un árbol de sintaxis abstracta, o AST, es una representación del código fuente (en este caso, la string de consulta MQL), en la que en el árbol de árbol a estructuras sintácticas en el código.

Macros MQL

MQL incluye una utilidad de definición de macros, def. Puedes usar la utilidad de definición de macros de MQL para reemplazar las operaciones repetidas, hacer que las consultas complejas sean más fáciles de leer y facilitar el desarrollo de consultas. Puedes definir macros para las operaciones de tablas y las funciones.

Macros para operaciones de tablas

Puedes escribir macros para crear nuevas operaciones de tabla. La sintaxis general se ve de la siguiente manera:

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

Para invocar la macro, usa la siguiente sintaxis:

@MACRO_NAME [MACRO_ARG [, MACRO_ARG]]

Por ejemplo, supongamos que utilizas la siguiente consulta para recuperar datos de uso de CPU:

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

La primera línea se puede reemplazar por la siguiente macro:

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

Para invocar la macro en la consulta, reemplaza la fetch original de la siguiente manera:

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

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

Puede reemplazar la segunda y la tercera línea por otras que toman argumentos. La definición de la macro enumera los parámetros a la macro y, en el cuerpo de la macro, consulta los parámetros de la macro como $MACRO_PARAMETER. Por ejemplo, puedes definir las siguientes macros:

def my_every time_arg = every $time_arg ;

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

Para invocar estas macros y proporcionar los argumentos, especifica los argumentos en una lista delimitada por comas en las invocaciones de macro. A continuación, se muestra la consulta con todas las macros definidas y sus invocaciones:

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 para funciones

Para las funciones de MQL, debes especificar cualquier parámetro en una lista delimitada por comas entre paréntesis. Los paréntesis distinguen una macro de función de una macro de operación de tabla. El paréntesis debe aparecer en la invocación, incluso si no hay argumentos.

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

Por ejemplo, la siguiente consulta recupera tablas para dos métricas, combina las dos tablas en una con dos columnas de valor y calcula la proporción de bytes recibidos en total de bytes para una columna llamada 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))]

Puedes reemplazar el cálculo received_percent con una macro como en el siguiente ejemplo:

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

Para invocar una macro de función, usa la siguiente sintaxis:

@MACRO_NAME([MACRO_ARG[, MACRO_ARG]])

Cuando invocas una macro de función sin argumentos, debes especificar los paréntesis vacíos para distinguir la invocación de la invocación de una macro de operación de tabla.

En el siguiente ejemplo, se muestra la consulta anterior con una macro para el cálculo de proporción:

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

Limitaciones

La función de macro MQL no admite lo siguiente:

  • Anidación de macros
  • Macros definidas de manera recurrente. Ningún cuerpo de macro puede hacer referencia a cualquier macro, incluida a sí misma, que aún no está completamente definida.
  • Uso de funciones definidas por macros como operaciones de tabla
  • Uso de argumentos de macro como nombres de funciones o operaciones de tabla.