Referência: classificação e filtragem

Esta seção complementa a documentação de referência dos recursos projects.alertPolicies e projects.notificationChannels na API Cloud Monitoring. Ela fornece detalhes sintáticos sobre os parâmetros filter e orderBy usados pela API nestes métodos list:

Princípios básicos de classificação e filtragem

O suporte para classificação e filtragem em uma operação list é indicado pela presença de campos de string filter e orderBy no corpo da solicitação de lista. Consulte a documentação de referência da API para ver se o corpo da solicitação tem esses campos. Ambos os campos usam uma linguagem simples para se referir aos campos no objeto que está sendo classificado ou filtrado.

Sintaxe de ordem de classificação

O campo orderBy consiste em uma lista separada por vírgulas de caminhos de campo que têm o sinal de menos como prefixo para reverter a ordem.

Por exemplo, user_label.team,display_name classifica por nome de equipe em ordem crescente e, para entradas com a mesma equipe, classifica por nome de exibição, também em ordem crescente. Se você adicionar um sinal de menos na frente de um dos campos separados por vírgula, esse campo será classificado em ordem decrescente. Por exemplo, se você estiver tentando reduzir o detalhamento dos títulos, poderá usar -display_name.size para classificar pelo tamanho do título, com objetos ordenados do título mais textual ao título mais curto.

Para fornecer um exemplo mais realista, user_label.team,display_name agrupa os resultados primeiro por equipe (em ordem lexicográfica) e, em seguida, organiza os resultados por título (também em ordem lexicográfica).

Formalmente, a sintaxe pode ser descrita como:

   ORDER_BY_SPEC :=
      # Comma-separated list of fields.
      ORDERED_FIELD_LIST

   ORDERED_FIELD_LIST :=
      # Single field on which to sort.
      ORDERED_FIELD

      # Sort by the first field and then by the remaining fields.
      | ORDERED_FIELD "," ORDERED_FIELD_LIST

   ORDERED_FIELD :=
      # Sort by the field in ascending order.
      FIELD_REFERENCE

      # Sort by the field in descending order.
      | "-" FIELD_REFERENCE

   FIELD_REFERENCE :=
      # Simple field reference
      FIELD_NAME

      # Map value or list index lookup. For string-valued keys, the
      # supplied key in this notation must be quoted.
      | FIELD_NAME "[" LITERAL "]"

   FIELD_NAME :=
      # Immediate element
      IDENTIFIER

      # Subfield dereference or map element dereference. Note that,
      # in the case of maps, the IDENTIFIER on the left can also
      # be the singular form of the name of the map. That is, it is
      # permitted to use `user_label.mykey` and not just
      # `user_labels.mykey`. This is done for consistency with the
      # metric filters which permit `resource.label.` and `metric.label.`
      # which are in the singular form even though the map is `labels`.
      | IDENTIFIER "." FIELD_NAME

   LITERAL :=
       # Number
       [0-9]+(.[0.9]+)?

       # String literal using single quotes. Note that strings must
       # always be quoted. This is to avoid ambiguity with attempting
       # to refer to the value of a field.
       |  '[^']*'

       # String literal using double quotes. Note that strings must
       # always be quoted. This is to avoid ambiguity with attempting
       # to refer to the value of a field.
       |  "[^"]*"

       # Literal boolean true.
       |  true

       # Literal boolean false.
       |  false

   IDENTIFIER :=
       # Non-digit followed by any number of letters or digits.
       [a-zA-Z_]+[a-zA-Z0-9_]*

Sintaxe do filtro

A sintaxe do filtro consiste em uma linguagem de expressão simples para construir um predicado a partir de um ou mais campos dos objetos que estão sendo filtrados. Negação, conjunção e disjunção são escritas usando as palavras-chave NOT, AND e OR. Os campos podem ser comparados com valores literais usando : (contenção), = (igualdade), > (maior), < (menor que), >= (maior que ou igual a), <= (menor ou igual a) e != (desigualdade). As funções integradas starts_with, ends_with e monitoring.regex.full_match ( RE2 sintaxe), bem como as propriedades incorporadas empty e size oferecem suporte para comparações mais avançadas.

Exemplos

Para retornar todas as entradas com um nome de exibição ou descrição não vazia em que o campo user_labels tenha a chave active definida (com qualquer valor):

(NOT display_name.empty OR NOT description.empty) AND user_labels='active'

Para retornar todas as entradas cuja descrição contém "cloud":

description:'cloud'

Para retornar todas as entradas cujo título corresponda a "temp XXXX":

display_name=monitoring.regex.full_match('Temp \\d{4}')

Especificação formal

A sintaxe da expressão de filtro pode ser resumida da seguinte maneira:

   FILTER_EXPRESSION :=
         # Negation
         "NOT" FILTER_EXPRESSION

         # Short-circuiting AND
         | FILTER_EXPRESSION "AND" FILTER_EXPRESSION

         # Short-circuiting OR
         | FILTER_EXPRESSION "OR" FILTER_EXPRESSION

         # Implicit short-circuiting AND
         | FILTER_EXPRESSION FILTER_EXPRESSION

         # Parenthesized sub-expression
         | "(" FILTER_EXPRESSION ")"

         # Basic expression
         | SIMPLE_EXPRESSION

   SIMPLE_EXPRESSION :=
         # Field implicitly converted to boolean
         FIELD_REFERENCE

         # Field binary comparison. Note that the right-hand side must
         # be compatible with the type on the left-hand side; one cannot
         # compare a number with a string. Sensible implicit conversions
         # are permitted, however; comparing an integer and double will
         # succeed with appropriate conversion/widening taking place.
         | FIELD_REFERENCE OP LITERAL

         # Function invocation
         | FIELD_REFERENCE "=" FUNCTION_EXPRESSION

   FIELD_REFERENCE :=
         # Simple field reference
         FIELD_NAME

         # Map value or list index lookup. For string-valued keys, the
         # supplied key in this notation must be quoted.
         | FIELD_NAME "[" LITERAL "]"

   FIELD_NAME :=
         # Immediate element
         IDENTIFIER

         # Subfield dereference or map element dereference. Note that,
         # in the case of maps, the IDENTIFIER on the left can also
         # be the singular form of the name of the map. That is, it is
         # permitted to use `user_label.mykey` and not just
         # `user_labels.mykey`. This is done for consistency with the
         # metric filters which permit `resource.label.` and `metric.label.`
         # which are in the singular form even though the map is `labels`.
         | IDENTIFIER "." FIELD_NAME

   OP :=
         # Equality comparison. Should be avoided for double-valued fields.
         "="

         # Less than.
         | "<"

         # Greater than.
         | ">"

         # Less than or equal.
         | "<="

         # Greater than or equal.
         | ">="

         # Containment. This is equivalent to '=' for numeric types.
         | ":"

         # Not equal.
         | "!="

   LITERAL :=
       # Number
       [0-9]+(.[0.9]+)?

       # String literal using single quotes. Note that strings must
       # always be quoted. This is to avoid ambiguity with attempting
       # to refer to the value of a field.
       |  '[^']*'

       # String literal using double quotes. Note that strings must
       # always be quoted. This is to avoid ambiguity with attempting
       # to refer to the value of a field.
       |  "[^"]*"

       # Literal boolean true.
       |  true

       # Literal boolean false.
       |  false

   FUNCTION_EXPRESSION :=
       # Starts with.
       "starts_with" "(" LITERAL ")"

       # Ends with.
       |  "ends_with" "(" LITERAL ")"

       # Has substring. Takes an optional second argument that indicates whether
       # the substring matching is case-sensitive (true) or not (false).
       # The default is false, providing case-insensitive matches.
       |  "has_substring" "(" LITERAL [, [true|false]] ")"

       # Regular expression match.
       |  "monitoring.regex.full_match" "(" LITERAL ")"

   IDENTIFIER :=
       # Non-digit followed by any number of letters or digits.
       [a-zA-Z_]+[a-zA-Z0-9_]*

Campos aceitos

Os campos que podem ser referenciados em filter ou orderBy dependem do tipo de objeto que está sendo listado.

AlertPolicy

Os seguintes campos podem ser referenciados em filter e orderBy ao enumerar objetos AlertPolicy:

  • name
  • display_name
  • documentation.content
  • documentation.mime_type
  • user_labels
  • conditions.size
  • combiner
  • ativada
  • notification_channels

NotificationChannel

Os seguintes campos podem ser referenciados em filter e orderBy ao enumerar objetos NotificationChannel:

  • name
  • tipo
  • display_name
  • descrição
  • rótulos
  • user_labels

Tópicos avançados

Casos de campo

Os nomes dos campos podem ser expressos nos formulários lower_case_with_underscores e camelCase. Ou seja, display_name e displayName são compatíveis.

Strings

Propriedades integradas

Os campos com valor de string têm automaticamente uma propriedade size que calcula o número de caracteres Unicode na string. Isso permite, por exemplo, um filtro como display_name.size > 3 AND display_name.size < 10. Além de size, as strings também têm uma propriedade bool empty.

Ordem de classificação

Ao listar uma string em orderBy, as strings são comparadas usando a ordenação lexicográfica por bytes na representação UTF-8 da string. As strings não são classificadas de acordo com a ordem de agrupamento Unicode.

Conversão booleana implícita

É possível converter implicitamente uma string em bool em um filtro como em user_label.enabled. Essa conversão não é idêntica ao teste de que a string não está vazia. Nessa conversão, o conteúdo da string é analisado para um valor booleano e as strings que analisam sem ambiguidades um valor booleano se apropriam desse valor booleano. Se a string não tiver valor booleano, as strings não vazias serão interpretadas como verdadeiras e as strings vazias serão interpretadas como falsas.

Strings que, indiferentes a maiúsculas, correspondem a "false", "f", "no", "n" ou "0" são consideradas falsas sem ambiguidades. As strings que, indiferentes a maiúsculas, correspondem a "true", "t", "yes", "y" ou "1" são consideradas verdadeiras sem ambiguidades.

Listas

Propriedades integradas

Os campos com valor de lista têm automaticamente uma propriedade size que calcula o número de elementos nessa lista. Por exemplo, é possível usar notification_channels.size em orderBy para classificar políticas de alertas pelo número de canais que eles notificam.

Uso em comparações binárias

Ao comparar um campo com valor de lista a um literal com um dos vários operadores binários, a comparação é interpretada como uma comparação baseada em elemento e, em seguida, calculando o OR dos resultados. Por exemplo, o filtro notification_channels:"123" será avaliado como verdadeiro se algum dos canais de notificação tiver "123" como substring. Para o operador !=, especificamente, a comparação por elemento é ANDed em vez de ORed. Em outras palavras, para !=, nenhum dos elementos pode ser correspondente. Ou, para reafirmar, x!=y é logicamente equivalente ao pseudocódigo x[0]!=y AND x[1]!=y AND ... AND x[x.size-1]!=y, enquanto x=y é logicamente equivalente ao pseudocódigo x[0]=y OR x[1]=y OR ... OR x[x.size-1]=y. Essa inconsistência foi projetada para lidar com a provável intent de x!=y e evitar confusão com uma expressão que retorna resultados com o valor proibido/filtrado.

Além de restringir a lista como um todo, também é possível consultar entradas de lista específicas por meio do operador de indexação ([]). Por exemplo, é possível usar notification_channels[0]:"123" para testar apenas o primeiro elemento. Um padrão (vazio, zero etc.) é gerado no caso de índices fora dos limites.

Conversão implícita em booleano

Quando especificada em um filtro sem uma comparação binária, uma lista será convertida implicitamente em booleano. Essa conversão é diferente de testar se a lista não está vazia. a_list e NOT a_list.empty retornam resultados diferentes para {false, false, false} ou qualquer outra lista não vazia em que os valores sejam todos ou convertam implicitamente no valor booleano false.

Maps

Propriedades integradas

Os campos com valor de mapa têm automaticamente uma propriedade size que calcula o número de elementos nesse mapa. Por exemplo, é possível usar user_labels.size em orderBy para classificar por número de rótulos de usuário definidos. Da mesma forma, uma propriedade empty com valor booleano também é gerada automaticamente.

Como testar a existência de chaves

Os mapas podem ser comparados a valores literais com os vários operadores binários compatíveis. A interpretação é logicamente equivalente a projetar o mapa em uma lista extraindo as chaves do mapa e executando a comparação. Para dar um exemplo, use user_labels="phase" para determinar se o mapa user_labels contém uma chave cujo valor é igual a "fase".

Como referenciar valores por chave

As entradas de mapa podem ser referenciadas usando uma destas duas notações: notação de ponto (.) e notação de índice ([]). Por exemplo, é possível usar user_labels.team ou user_labels["team"] para se referir ao valor correspondente à chave "equipe" no campo user_labels. Para consistência com a API Metrics que usa prefixos metric.label. e resource.label. em vez de metric.labels. e resource.labels., os campos de mapa também podem ser referenciados usando a forma singular do nome (ou seja, user_label.team também é permitido). Observe que, para chaves chamadas size ou empty, é preciso usar a notação de índice. O uso de notação de ponto fará referência às propriedades do mapa integradas.

Conversão implícita em booleano

Em conversões implícitas em booleanos, um mapa é considerado verdadeiro se não estiver vazio e pelo menos um valor do mapa for convertido implicitamente em verdadeiro. Isso não é a mesma coisa que testar se o mapa não está vazio.

Como ordenar por tipos compostos

Todos os campos que podem ser referenciados em um filtro também podem ser referenciados em order_by. Isso também se aplica a tipos complexos e compostos. A ordem de classificação desses tipos é estável e bem definida, embora não seja necessariamente intuitiva. Portanto, esse uso não é recomendado, mas permitido.

Listas

As listas são comparadas usando uma comparação lexicográfica por elementos, com a lista menor em primeiro lugar se os elementos comuns forem iguais. Para dar um exemplo, {0, 1} é menor que {0, 2}, mas maior que {0}.

Maps

Os mapas são comparados realizando uma comparação por elementos entre os valores dos mapas correspondentes à união das chaves. Para chaves definidas em um mapa, mas não no outro, um valor padrão (vazio, zero etc.) é usado para a comparação. Como exemplo, {"x":0, "y":0} é menor que {"x":1, "y":1}, mas maior que {"a":-1} e igual a {}.