DataPrime operadores
Este guia fornece um glossário dos operadores do IBM® Cloud Logs DataPrime.
block
A negação de filter. Filtra todos os eventos em que a condição é verdadeira. O mesmo efeito pode ser obtido com o uso do site filter com !(condition).
block $d.status_code >= 200 && $d.status_code <= 299 # Leave all events which don't have a status code of 2xx
Os dados são expostos usando os seguintes campos:
-
$m - Metadados do evento
timestampseverity- Os valores possíveis sãoVerbose,Debug,Info,Warning,Error,Criticalpriorityclass- Os valores possíveis sãohigh,medium,lowlogid
-
$l - Rótulos de eventos
applicationnamesubsystemnamecategoryclassnamecomputernamemethodnamethreadidipaddress
-
$d -Os dados do usuário
bottom
Nenhuma variação de agrupamento: Limita as linhas retornadas a um número especificado e ordena o resultado por um conjunto de expressões.
order_direction := "descending"/"ascending" according to top/bottom
bottom <limit> <result_expression1> [as <alias>] [, <result_expression2> [as <alias2>], ...] by <orderby_expression> [as alias>]
Por exemplo, a consulta a seguir:
bottom 5 $m.severity as $d.log_severity by $d.duration
Resultará em registros do seguinte formato:
[
{ "log_severity": "Debug", "duration": 1000 }
{ "log_severity": "Warning", "duration": 2000 },
...
]
Variação de agrupamento: Limita as linhas retornadas a um número especificado e as agrupa por um conjunto de expressões de agregação e as ordena por um conjunto de expressões.
order_direction := "descending"/"ascending" according to top/bottom
bottom <limit> <(groupby_expression1|aggregate_function1)> [as <alias>] [, <(groupby_expression2|aggregate_function2)> [as <alias2>], ...] by <(groupby_expression1|aggregate_function1)> [as <alias>]
Por exemplo, a consulta a seguir:
bottom 10 $m.severity, count() as $d.number_of_severities by avg($d.duration) as $d.avg_duration
Resultará em registros do seguinte formato:
[
{ "severity": "Warning", "number_of_severities": 50, avg_duration: 1000 },
{ "severity": "Debug", "number_of_severities": 10, avg_duration: 2000 }
...
]
As funções de agregação compatíveis estão listadas na seção "Funções de agregação".
choose
Deixe apenas os caminhos de teclado fornecidos, descartando todas as outras chaves. Oferece suporte total a keypaths aninhados na saída.
(choose|select) <keypath1> [as <new_keypath>],<keypath2> [as <new_keypath>],...
Exemplos:
choose $d.mysuperkey.myfield
choose $d.my_superkey.mykey as $d.important_value, 10 as $d.the_value_ten
convert
Converta os tipos de dados das chaves.
A palavra-chave datatypes é opcional e pode ser usada para facilitar a leitura.
(conv|convert) [datatypes] <keypath1>:<datatype1>,<keypath2>:<datatype2>,...
Exemplos:
convert $d.level:number
conv datatypes $d.long:number,$d.lat:number
convert $d.data.color:number,$d.item:string
count
Retorna uma única linha contendo o número de linhas produzidas pelos operadores anteriores.
count [into <keypath>]
Um alias pode ser fornecido para substituir o keypath onde o resultado será gravado.
Por exemplo, a seguinte parte de uma consulta:
count into $d.num_rows
Resultará em uma única linha com o seguinte formato:
{ "num_rows": 7532 }
countby
Retorna uma linha que conta todas as linhas agrupadas pela expressão.
countby <expression> [as <alias>] [into <keypath>]
Um alias pode ser fornecido para substituir o caminho de chave no qual o resultado será gravado.
Por exemplo, a seguinte parte de uma consulta
countby $d.verb into $d.verb_count
Resultará em uma linha para cada grupo.
Ele é funcionalmente idêntico ao
groupby $data.verb calculate count() as $d.verb_count
create
Crie uma nova chave e defina seu valor como o resultado da expressão. A criação de chaves é granular, o que significa que as chaves pai no caminho não são substituídas.
(a|add|c|create) <keypath> from <expression> [on keypath exists (fail|skip|overwrite)] [on keypath missing (fail|create|skip)] [on datatype change (skip|fail|overwrite)
A criação pode ser controlada com a adição das seguintes cláusulas:
-
A adição do endereço
keypath existspermite escolher o que fazer quando o caminho da chave já existe.-
overwrite- Substitui o valor antigo. Este é o valor padrão -
fail- Falha na consulta -
skip- Ignora a criação da chave
-
-
Adicionar
keypath missingescolhe o que fazer quando o novo caminho de chave não existir.-
create- Cria a chave. Este é o valor padrão -
fail- Falha na consulta -
skip- Ignora a criação da nova chave
-
-
Adding on
datatype changedescolhe o que fazer se a chave já existir e os novos dados alterarem o tipo de dados do valor.-
overwrite- Substitui o valor. Este é o valor padrão. -
fail- Falha na consulta -
skip- Deixa a chave com o valor (e o tipo) original
-
Exemplos:
create $d.radius from 100+23
c $d.log_data.truncated_message from $d.message.substring(1,50)
c $data.trimmed_name from $data.username.trim()
create $d.temperature from 100*23 on datatype changed skip
distinct
Retorna uma linha para cada combinação distinta das expressões fornecidas.
distinct <expression> [as <alias>] [, <expression_2> [as <alias_2>], ...]
Esse operador é funcionalmente idêntico ao groupby sem nenhuma função agregada.
enrich
Enriqueça seus registros usando contexto adicional de uma tabela de pesquisa.
Carregue sua tabela de pesquisa usando Fluxo de dados > Data Enrichment > Custom Enrichment.
enrich <value_to_lookup> into <enriched_key> using <lookup_table>
-
value_to_lookup- Uma expressão de cadeia de caracteres que será pesquisada na tabela de pesquisa. -
enriched_key- Chave de destino para armazenar o resultado do enriquecimento. -
lookup_table- O nome da tabela de enriquecimento personalizado a ser usada.
As colunas da tabela serão adicionadas como subchaves à chave de destino. Se value_to_lookup não for encontrado, a chave de destino será nula. Em seguida, você pode filtrar os resultados usando os recursos do site DataPrime, como
filtrar os registros por valor específico no campo enriquecido.
Exemplo:
O registro original:
{
"userid": "111",
...
}
A tabela de pesquisa de enriquecimento personalizado chamada my_users:
| ID | Nome | Departamento |
|---|---|---|
| 111 | John | Finanças |
| 222 | Emily | IT |
Executando a seguinte consulta:
enrich $d.userid into $d.user_enriched using my_users
Resultará no seguinte registro enriquecido:
{
"userid": "111",
"user_enriched": {
"ID": "111",
"Name": "John",
"Department": "Finance"
},
...
}
Considere o seguinte ao usar o site enrich:
-
Execute a fonte de consulta DataPrime
lookup_tablepara visualizar a tabela de enriquecimento. -
Se o registro original já contiver a chave enriquecida:
-
Se
value_to_lookupexistir emlookup_table, as subchaves serão atualizadas com o novo valor. Se ovalue_to_lookupnão existir, seu valor atual permanecerá. -
Quaisquer outras subchaves que não sejam colunas no site
lookup_tablepermanecerão com seus valores existentes.
-
-
Todos os valores no site
lookup_tablesão considerados cadeias de caracteres. Isso significa que:-
O endereço
value_to_lookupdeve estar em um formato de cadeia de caracteres. -
Todos os valores são enriquecidos em um formato de cadeia. Em seguida, você pode convertê-los em seu formato preferido (por exemplo, JSON, carimbo de data/hora) usando as funções apropriadas.
-
extract
Extrai dados de algum valor de string em um novo objeto. Há suporte para vários métodos de extração.
(e|extract) <expression> into <keypath> using <extraction-type>(<extraction-params>) [datatypes keypath:datatype,keypath:datatype,...]
Veja a seguir os métodos de extração suportados e seus parâmetros:
-
regexp- Criar um novo objeto com base em grupos de captura regexp -
e- Uma expressão regular com nomes capture-groups.
Exemplo:
extract $d.my_text into $d.my_data using regexp(e=/user (?<user>.*) has logged in/)
-
kv- Extrair um novo objeto de uma cadeia de caracteres que contém pares chave=valor chave=valor. -
pair_delimiter- O delimitador a ser esperado entre os pares. O padrão é (um espaço) -
key_delimiter- O delimitador que se espera separar entre uma chave e um valor. O padrão é =.
Exemplos:
extract $d.text into $d.my_kvs using kv()
e $d.text into $d.my_kvs using kv(pair_delimiter=' ',key_delimiter='=')
-
jsonobject- Extrair um novo objeto de uma cadeia de caracteres que contém um objeto json codificado, tentando potencialmente desfazer o escape da cadeia de caracteres antes de decodificá-la em um json -
max_unescape_count- Número máximo de níveis de escape a serem removidos antes de analisar o json. O padrão é 1. Quando definido como 1 ou mais, o mecanismo detectará se o valor contém uma cadeia de caracteres JSON com escape e fará o unescape até que a contagem analisável ou máxima de unescape seja excedida.
Exemplo:
e $d.json_message_as_str into $d.json_message using jsonobject(max_unescape_count=1)
É possível fornecer informações de tipo de dados como parte da extração, usando a cláusula datatypes. Por exemplo, adicionar os tipos de dados my_field:number a uma extração faria com que a extração my_field keypath
fosse um número em vez de uma cadeia de caracteres. Por exemplo:
extract $d.my_msg into $d.data using kv() datatypes my_field:number
Os dados extraídos sempre entram em um novo caminho de chave como um objeto, permitindo o processamento adicional das novas chaves dentro desse novo objeto. Por exemplo:
# Assuming a dataset which look like that:
{ "msg": "query_type=fetch query_id=100 query_results_duration_ms=232" }
{ "msg": "query_type=fetch query_id=200 query_results_duration_ms=1001" }
# And the following DataPrime query:
source logs
| extract $d.msg into $d.query_data using kv() datatypes
query_results_duration_ms:number
| filter $d.query_data.query_results_duration_ms > 500
# The results will contain only the second message, in which the duration is greater than 500 ms
filter
Filtra eventos, deixando apenas os eventos para os quais a condição é avaliada como verdadeira.
(f|filter|where) <condition-expression>
Exemplos:
f $d.radius > 10
filter $m.severity.toUpperCase() == 'INFO'
filter $l.applicationname == 'myapp'
filter $l.applicationname == 'myapp' && $d.msg.contains('failure')
A comparação com null funciona somente para valores escalares e sempre retornará null em subárvores JSON.
Ao usar uma condição para comparar um caminho de chave com nulo, isso só funcionará em valores escalares (cadeia de caracteres, número, registro de data e hora etc.). Para objetos JSON em um determinado documento, a comparação com null sempre retornará null.
Use filtros com funções para realizar pesquisas complexas.
Exemplos:
filter in($l.applicationname, 'ibm-audit-event', 'ibm-platform-logs') #
filter ipInSubnet(ip_address, '155.64.5.20/24')
e - Filtro para endereços IP em um determinado intervalo. o filtro pode ser associado a funções para realizar pesquisas complexas com muito pouca sintaxe, por exemplo, usando a função ipInSubnet:
filtro ipInSubnet(ip_address, ' 154.67.8.20/24 ')
groupby
Agrupa os resultados dos operadores anteriores de acordo com as expressões de agrupamento especificadas e calcula as funções agregadas para cada grupo criado.
groupby <grouping_expression> [as <alias>] [, <grouping_expression_2> [as <alias_2>], ...] [calculate]
<aggregate_function> [as <result_keypath>]
[, <aggregate_function_2> [as <result_keypath_2], ...]
Por exemplo, a consulta a seguir:
groupby $m.severity calculate sum($d.duration)
Resultará em registros do seguinte formato:
{ "severity": "Warning", "_sum": 17045 }
Os caminhos de teclado para as expressões de agrupamento sempre estarão em $d. Usando a palavra-chave as, podemos renomear o caminho-chave para as expressões de agrupamento e funções de agregação. Por exemplo:
groupby $l.applicationname as $d.app calculate sum($d.duration) as $d.sum_duration
Resultará em registros do seguinte formato:
{ "app": "web-api", "sum_duration": 17045 }
Ao fazer consultas com o operador groupby, você pode aplicar uma função de agregação (como avg, max, sum) ao grupo
de resultados. Esse recurso permite que você manipule uma expressão de agregação dentro da própria expressão, o que possibilita calcular e manipular os dados simultaneamente.
join
Join mescla os resultados da consulta atual (esquerda) com uma segunda consulta (direita) com base em uma condição especificada. Ele oferece vários formulários para controlar como os dados são combinados e suporta aninhamento, permitindo
que a consulta correta inclua seu próprio comando join.
Join suporta três variações:
join left|join- Para cada evento na consulta à esquerda, o comando seleciona um evento correspondente da consulta à direita com base na condição especificada. Se nenhuma correspondência for encontrada, as linhas serão incluídas para todos os eventos na consulta
à esquerda. As linhas não correspondentes da consulta correta são definidas como
null. join full- Retorna uma linha para cada evento, incluindo aqueles que podem não ter uma correspondência em nenhuma das consultas (esquerda ou direita), preenchendo os valores ausentes com
null. join inner- Retorna apenas as linhas em que há resultados não nulos de ambas as consultas.
join cross- Emparelha cada linha da consulta da esquerda com cada linha da consulta da direita, gerando o produto cartesiano completo. Diferentemente de outros tipos de
join, ojoin crossnão é compatível comonouusing conditions. Funciona de forma semelhante a umjoin inner, mas sem qualquer filtragem, retornando todas as combinações de linhas possíveis.
Para left (padrão), inner e full, você pode especificar uma condição join usando a palavra-chave on ou um caminho-chave usando a palavra-chave keyword. O produto cartesiano
é filtrado para reter apenas as linhas em que a condição é verdadeira ou em que os valores do caminho-chave correspondem em ambos os lados.
Como todas as uniões, independentemente do modificador, são baseadas no produto cartesiano, podem ocorrer resultados duplicados se a condição join corresponder várias vezes. Para evitar a duplicação não intencional, considere o
pré-processamento de subconsultas, por exemplo, usando distinct.
Sintaxe:
<left_side_query> | join [left/inner/full] (<right_side_query>) on <condition> into <right_side_target>
<left_side_query> | join [left/inner/full] (<right_side_query>) using <join_keypath_1> [, <join_keypath_2>, ...] into <right_side_target>
<left_side_query> | join cross (<right_side_query>) into <right_side_target>
Em que:
-
<right_side_query>- O endereço<right_side_query>indica a nova consulta a ser unida. -
<left_side_query>- O<left_side_query>indica a consulta inicial, por exemplo, na consultasource logs | filter x != null | join ..., a consulta do lado esquerdo ésource logs | filter x != null. -
<condition>- A condição se os resultados de ambas as consultas devem ser unidos.Na condição, você pode usar os prefixos
left=>eright=>para se referir aos eventos das consultas à esquerda e à direita, respectivamente. No entanto, isso não é necessário se um caminho-chave existir em apenas uma das consultas.Ao usar o operador
==(igualdade) em sua condição, ele deve comparar um keypath da consulta à esquerda com um keypath da consulta à direita. No entanto, como os keypaths devem ser exclusivos ou prefixados comleft=>ouright=>, a ordem dos operandos não é importante. -
<join_keypath_n>-<join_keypath_n>como uma chave de união significa unir resultados em que um determinado caminho-chave é igual nos resultados da consulta do lado esquerdo e da consulta do lado direito. -
<right_side_target>- O keypath onde os dados unidos serão adicionados à consulta atual.
joinexemplo
Você tem uma tabela de enriquecimento personalizada chamada users que fornece informações sobre IDs relacionadas a nomes:
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
E esses dados fornecem eventos de login e IDs de usuário, mas não o nome de usuário associado aos IDs de usuário.
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z" }
Usando o site join, você pode usar uma consulta para retornar dados que incluam os dados desejados.
source users | join (source logs | countby userid) on id == userid into logins
Essa consulta é processada da seguinte forma:
-
O
sourceé a tabela de enriquecimento personalizada (users). -
Em
join, é gerada uma contagem pelo campouserid. Isso nos dá nossas estatísticascount. -
O campo
idna tabela de enriquecimento personalizado é comparado com o campouseridnos registros. -
O resultado é inserido na chave
logins. Se a chaveloginsjá existir na consulta à esquerda, ela será substituída.
Por exemplo:
{ "id": "111", "name": "John", "logins": { "userid": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "userid": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
O resultado da consulta do lado direito agora está dentro do campo logins. Observe que não houve logins para o ID de usuário 333 (Alice), portanto, o campo logins é null porque não houve resultado correspondente
à condição join.
join exemplo com a palavra-chave using
Considere se nosso conjunto de dados de login é:
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
Nesse caso, os dados em ambos os lados da união incluem o campo id. Nesse caso, a palavra-chave using pode ser usada para aproveitar os dados comuns:
source users | join (source logins | countby id) using id into logins
O resultado será semelhante, mas, em vez de userid, o campo id será retornado.
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
Se você tiver dois campos com nomes diferentes, mas que simplificariam sua consulta em join, poderá usar move para mover um dos campos de
modo que os caminhos-chave coincidam em ambos os lados.
join exemplo usando as palavras-chave left=> e right=>
Você pode usar os prefixos left=> e right=> para se referir aos eventos das consultas à esquerda e à direita. No entanto, isso não é necessário se um caminho-chave existir em apenas uma das consultas.
Usando os dados do exemplo anterior, considere a consulta:
source users | join (source logins | countby id) on left=>id == right=>id into logins
Isso é necessário porque ambos os conjuntos de dados contêm um campo com o mesmo nome (id). Para que o DataPrime identifique um campo de forma exclusiva, ele deve saber a qual lado da consulta estamos nos referindo. Essa consulta
resultará no mesmo resultado que a anterior, que usou a palavra-chave using.
Ao usar o operador == (igualdade) em sua condição, ele deve comparar um keypath da consulta à esquerda com um keypath da consulta à direita. No entanto, como os keypaths devem ser exclusivos ou prefixados com left=> ou right=>, a ordem dos operandos não é importante.
join fullexemplo
Você tem uma tabela de enriquecimento personalizada chamada users que fornece informações sobre IDs relacionadas a nomes:
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
E considere este conjunto de dados:
{ "id": "001", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
O segundo conjunto de documentos (consulta à direita) inclui uma entrada de registro com "id": "001" que não existe no primeiro conjunto de documentos (consulta à esquerda). Se você usar uma união padrão, essa
entrada da consulta correta será ignorada e não aparecerá no resultado. Para garantir que todos os campos do site id sejam incluídos na saída, independentemente de aparecerem ou não na consulta à esquerda ou à direita, você
pode usar join full:
source users | join full (source logins | countby id) using id into logins
Essa consulta resulta em:
{ "id": "001", "name": "null", "logins": { "id": "001", "_count": 1 } }
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
{ "id": "333", "name": "Alice", "logins": null }
Ao usar join full, todos os campos id de ambos os conjuntos de dados são preservados, e todos os valores ausentes são definidos como null.
join full é particularmente útil quando os resultados de ambas as consultas incluem intervalos de tempo. Por exemplo, se os resultados da consulta à esquerda não tiverem um intervalo de tempo para uma hora específica (por exemplo,
XX:XX:XX), com join full esse ponto de dados será incluído. Isso é especialmente útil para comparar duas séries temporais em um gráfico.
join innerexemplo
Se você quiser remover qualquer linha ou resultado de coluna das consultas à esquerda ou à direita que produzam um valor nulo, use join inner.
Usando os dados anteriores, essa consulta remove as linhas com dados não correspondentes de ambos os lados:
source users | join inner (source logins | countby id) using id into logins
-
A consulta à esquerda
source usersrecupera o conjunto de dados de usuários que contém os camposidename. -
A consulta correta (
source logins | countby id) recupera o conjunto de dados de logins, agrupando poride contando as ocorrências de cadaid. -
join innercorresponde às linhas em queidexiste em ambos os conjuntos de dados e mescla os dados em um único registro. -
As linhas sem correspondência em nenhum dos conjuntos de dados são excluídas dos resultados finais.
Nesse caso, para os dois conjuntos de documentos acima, os resultados serão os seguintes:
{ "id": "111", "name": "John", "logins": { "id": "111", "_count": 2 } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "_count": 3 } }
join crossexemplo
join cross combina cada linha da consulta da esquerda com cada linha da consulta da direita, produzindo um produto cartesiano dos dois conjuntos.
Suponha que temos os seguintes documentos de uma tabela de enriquecimento personalizada chamada users.
{ "id": "111", "name": "John" }
{ "id": "222", "name": "Emily" }
{ "id": "333", "name": "Alice" }
Agora, considere esse conjunto de documentos denominado logs.
{ "id": "111", "timestamp": "2022-01-01T12:00:00Z" }
{ "id": "111", "timestamp": "2022-01-01T12:30:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
{ "id": "222", "timestamp": "2022-01-01T13:00:00Z" }
A consulta a seguir produzirá um produto cartesiano dos conjuntos de dados users e logs porque join cross emparelha todas as linhas da consulta à esquerda com todas as linhas da consulta à direita, independentemente
de quaisquer condições de correspondência.
source users | join cross (source logs) into logins
{ "id": "111", "name": "John", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "111", "name": "John", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "222", "name": "Emily", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "111", "timestamp": "2022-01-01T12:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "111", "timestamp": "2022-01-01T12:30:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
{ "id": "333", "name": "Alice", "logins": { "id": "222", "timestamp": "2022-01-01T13:00:00Z" } }
A consulta resulta no emparelhamento de cada usuário com cada entrada de registro: 3 linhas de users multiplicadas por 5 linhas de logs, resultando em 15 linhas. Cada usuário (John, Emily,
Alice) é emparelhado com cada entrada de registro.
O uso do join cross é especialmente útil quando você está interessado em ver um quadro completo dos seus dados e, em seguida, adicionar um left ou right join a esses resultados.
Limitações e considerações
Há limitações e considerações ao incluir o site join em uma consulta:
-
A condição
joinsuporta apenas a igualdade de keypath (==). Se forem necessárias várias condições de igualdade, elas podem ser combinadas com&&(logical and). -
Um dos lados da união (consulta atual ou consulta de união) deve ser pequeno (< 200MB ). Você pode usar
filtereremovepara reduzir o tamanho da consulta. -
As uniões externas à esquerda exigem que todas as colunas na condição sejam não nulas. As colunas nulas não serão unidas. Para incluir colunas nulas na consulta à direita, use
join full. Para excluir todas as colunas nulas produzidas pelas uniões à esquerda e à direita, usejoin inner.
limit
Limita a saída aos primeiros event-count eventos.
limit <event-count>
Exemplo:
limit 100
move
Mover uma chave (incluindo suas chaves secundárias, se houver) para um novo local.
(m|move) <source-keypath> to <target-keypath>
Exemplos:
move $d.my_data.hostname to $d.my_new_data.host
m $d.kubernetes.labels to $d.my_labels
multigroupby
multigroupby concatena os resultados de duas ou mais consultas incorporando groupby em um único conjunto de dados.
Use o site multigroupby para:
-
Eficiência: Os dados são verificados apenas uma vez para várias consultas.
-
Sincronização: Os resultados permanecem coerentes, evitando discrepâncias que podem surgir ao executar consultas separadas.
multigroupby (<grouping_expression_1> as <alias> [, <grouping_expression_2> as <alias_2>, ...]) [, (<grouping_expression_1> as <alias> [, <grouping_expression_2> as <alias_2>, ...]), ...][calculate] <aggregation_expression> [as <result_keypath>] [, <aggregation_expression_2> [as <result_keypath_2], ...]
Ao usar o mesmo pseudônimo app para ambos os agrupamentos, o mesmo significado semântico é apresentado como um campo unificado. No próximo exemplo, são usados aliases diferentes e os dados são combinados, mas não mesclados.
Exemplo - Multigroupby com o mesmo alias
Neste exemplo, queremos agrupar nossos registros da seguinte forma:
-
Primeiro por
applicationname(app) e depois porsubsystemname(ss), fornecendo contagens detalhadas para cada combinação. -
Em seguida, independentemente de
applicationname, obtém-se a contagem total de registros para cada aplicativo, independentemente desubsystems.
source logs
| multigroupby ($l.applicationname as app, $l.subsystemname as ss),($l.applicationname as app) calculate count() | orderby app,ss
O resultado será semelhante a:
[
{
"_count0": 241,
"app": "monitoring24",
"ss": "NO_SUBSYSTEM_NAME"
},
{
"_count0": 231,
"app": "monitoring24",
"ss": "logs-opentelemetry-agent"
},
{
"_count0": 15,
"app": "monitoring24",
"ss": "logs-opentelemetry-collector"
},
{
"_count0": 487,
"app": "monitoring24",
"ss": null
}
]
As três primeiras linhas representam as contagens para cada combinação exclusiva de app e ss. Por exemplo, há 241 registros em que o aplicativo (app) é monitoring24 e o subsistema (ss)
é NO_SUBSYSTEM_NAME. Da mesma forma, há 231 registros para o mesmo aplicativo, mas com o subsistema logs-opentelemetry-agent, e assim por diante.
A última linha fornece uma contagem total de logs para o aplicativo monitoring24, agregando todos os subsistemas. Aqui, _count0 é 487, a soma de todas as contagens detalhadas acima. O campo ss é null para indicar que esse é o total para o aplicativo como um todo.
Ao usar o mesmo pseudônimo app para ambos os agrupamentos, o mesmo significado semântico é apresentado como um campo unificado. No próximo exemplo, são usados aliases diferentes e os dados são combinados, mas não mesclados.
Exemplo - Multigroupby com aliases diferentes
Agora, considere os efeitos da introdução de dois aliases diferentes para as consultas. Nesse caso, o primeiro agrupamento é rotulado como app1 para applicationname combinado com ss, enquanto o segundo
agrupamento é rotulado como app2 para applicationname alone.
source logs | multigroupby ($l.applicationname as app1, $l.subsystemname as ss),($l.applicationname as app2) calculate count()
O resultado será semelhante a:
[
{
"_count0": 241,
"app1": "monitoring24",
"app2": null,
"ss": "logs-opentelemetry-agent"
},
{
"_count0": 231,
"app1": "monitoring24",
"app2": null,
"ss": "logs-opentelemetry-collector"
},
{
"_count0": 15,
"app1": "monitoring24",
"app2": null,
"ss": "no_subsystem_name"
},
{
"_count0": 487,
"app1": null,
"app2": "monitoring24",
"ss": null
}
]
Ao introduzir aliases separados (app1 e app2), a consulta mantém a distinção entre os dois agrupamentos em vez de mesclar os dados. As linhas em que app1 é preenchido e app2 é null correspondem ao agrupamento detalhado por applicationname e subsystemname. Por exemplo, 241 registros estão associados a app1 = "monitoring24" e ss = "logs-opentelemetry-agent".
Isso segue a primeira lógica de agrupamento.
A linha em que app2 é preenchida e app1 é null reflete a contagem total do segundo agrupamento, em que os registros são agregados apenas por applicationname. Para app2 = "monitoring24",
a contagem é 487, e tanto app1 quanto ss são null para indicar essa agregação de nível superior.
Ao usar aliases separados (app1 e app2), a consulta não mescla os dados, mas deixa claro a qual grupo cada resultado pertence. A lógica geral permanece a mesma: contagens detalhadas para combinações específicas e
contagens agregadas para o total.
Multigroupby limitações
multigroupby não retorna linhas duplicadas para conjuntos de grupos duplicados.
Se você executar o site multigroupby com app e ss, o resultado esperado (se as duplicatas forem permitidas) poderá ser semelhante a este:
[
{"app": "monitoring24", "ss": "logs-opentelemetry-agent", "_count0": 2},
{"app": "monitoring24", "ss": "logs-opentelemetry-collector", "_count0": 2}
]
Devido a essa limitação, o site multigroupby mesclará essas duplicatas e retornará apenas uma linha para cada combinação exclusiva, mesmo que essa combinação ocorra várias vezes nos dados:
[
{"app": "monitoring24", "ss": "logs-opentelemetry-agent", "_count0": 2}
]
orderby / sortby / order by / sort by
Classifique os dados por ordem ascendente/descendente do valor da expressão. Há suporte para ordenação por várias expressões.
(orderby|sortby|order by|sort by) <expression> [(asc|desc)] , ...
Exemplos:
orderby $d.myfield.myfield
orderby $d.myfield.myfield:number desc
sortby $d.myfield desc
A classificação de valores numéricos pode ser feita por meio da conversão da expressão para o tipo:, por exemplo, <expression>: number. Em alguns casos, isso será inferido automaticamente pelo mecanismo.
redact
Substitui todas as substrings que correspondem a um padrão regexp de algum valor keypath, ocultando efetivamente o conteúdo original.
A palavra-chave correspondente é opcional e pode ser usada para aumentar a legibilidade.
redact <keypath> [matching] /<regular-expression>/ to '<redacted_str>'
redact <keypath> [matching] <string> to '<redacted_str>'
Exemplos:
redact $d.mykey /[0-9]+/ to 'SOME_INTEGER'
redact $d.mysuperkey.user_id 'root' to 'UNKNOWN_USER'
redact $d.mysuperkey.user_id matching 'root' to 'UNKNOWN_USER'
remove
Remove um keypath do objeto.
r|remove <keypath1> [ "," <keypath2> ]...
Exemplos:
r $d.mydata.unneeded_key
remove $d.mysuperkey.service_name, $d.mysuperkey.unneeded_key
replace
Substitui o valor de alguma chave por um novo valor.
Se o valor de substituição alterar o tipo de dados do caminho-chave, as seguintes opções estarão disponíveis:
-
skip- A substituição será ignorada -
fail- A consulta falhará -
overwrite- O novo valor substituirá o anterior, alterando o tipo de dados do keypath
replace <keypath> with <expression> [on datatype changed skip/fail/overwrite]
Exemplos:
replace $d.message with null
replace $d.some_superkey.log_length_plus_10 with $d.original_log.length()+10 on datatype changed overwrite
roundtime
Arredonda a hora do evento em algum intervalo de tempo, possivelmente criando uma nova chave para o resultado.
-
Se
source-timestampnão for fornecido,$m.timestampserá usado como o registro de data e hora de origem. -
Se
source-timestampfor fornecido, ele deverá ser do tipo (ou convertido para)timestamp.
Por padrão, o resultado arredondado é gravado de volta no keypath de origem source-timestamp. Se em target-keypath for fornecido, então source-timestamp não será modificado e o resultado será gravado em
um novo target-keypath.
Os intervalos de tempo suportados são:
- Xns - X nanossegundos (tenha cuidado com a resolução do registro de data e hora de origem)
- Xms - X milissegundos
- Xs - X segundos
- Xm - X minutos
- Xh - X horas
- Xd - X dias
E qualquer combinação de unidades de tempo maiores para menores, por exemplo, 1h30m15s.
roundtime [source-timestamp] to <time-interval> [into <target-keypath>]
Exemplos:
roundtime to 1h into $d.tm
roundtime $d.timestamp to 1h
roundtime $d.my_timestamp: timestamp to 60m
roundtime to 60s into $d.rounded_ts_to_the_minute
source
Defina a fonte de dados na qual sua consulta DataPrime se baseia.
(source|from) <data_store>
Onde data_store pode ser qualquer um:
-
logs -
O nome do enriquecimento personalizado. Nesse caso, o comando exibirá a tabela de enriquecimento personalizada.
Exemplos:
source logs
stitch
O comando stitch executa uma união horizontal de dois conjuntos de dados, combinando-os lado a lado. Ele alinha as linhas de um conjunto de dados com as linhas de outro e concatena suas colunas, criando um conjunto de dados único
e unificado.
Ao usar o comando stitch:
-
Os conjuntos de dados devem ser ordenados, pois as linhas são combinadas em sequência (ou seja, a linha 1 do conjunto de dados A é costurada com a linha 1 do conjunto de dados B).
-
Se um conjunto de dados tiver mais linhas do que o outro, as linhas não correspondentes terão valores nulos nas colunas unidas.
-
O conjunto de dados resultante conterá todas as colunas de ambos os conjuntos de dados.
stitch é diferente de union. stitch combina conjuntos de dados horizontalmente, anexando colunas linha por linha. union anexa linhas verticalmente, empilhando conjuntos de dados uns sobre os
outros.
... | stitch (<subquery>) into <target-keypath>
Exemplo:
Você tem essas tabelas de enriquecimento personalizadas:
sales conjunto de dados:
{ "product": "Widget", "sales": 100 }
{ "product": "Gadget", "sales": 200 }
{ "product": "Dashboard", "sales": 150 }
revenue conjunto de dados:
{ "product": "Widget", "revenue": 5000 }
{ "product": "Gadget", "revenue": 8000 }
{ "product": "Dashboard", "revenue": 6000 }
Nessa consulta, você combinará esses conjuntos de dados lado a lado, garantindo que cada linha de um conjunto de dados se alinhe com a linha correspondente do outro:
source sales | orderby product
| stitch (source revenue | orderby product) into combined_data
-
source salesobtém todas as linhas do conjunto de dadossales, que contém produtos e seus respectivos números de vendas. -
orderby productclassifica o conjunto de dadossalespelo campoproductpara criar uma ordem consistente para o alinhamento de linhas. -
stitch (source revenue | orderby product)obtém linhas do conjunto de dadosrevenuee as classifica pelo campoproduct. Os conjuntos de dadossaleserevenuesão combinados horizontalmente, alinhando as linhas com base em sua ordem após a classificação. -
into combined_dataarmazena o conjunto de dados combinado em uma variável chamadacombined_data.
O resultado da consulta é:
{ "product": "Widget", "sales": 100, "combined_data": { "product": "Widget", "revenue": 5000 } }
{ "product": "Gadget", "sales": 200, "combined_data": { "product": "Gadget", "revenue": 8000 } }
{ "product": "Dashboard", "sales": 150, "combined_data": { "product": "Dashboard", "revenue": 6000 } }
Se os conjuntos de dados tiverem linhas desiguais, o comando stitch preencherá os valores ausentes com null.
Por exemplo, considere os seguintes conjuntos de dados:
sales conjunto de dados (3 linhas):
{ "product": "Widget", "sales": 100 }
{ "product": "Gadget", "sales": 200 }
{ "product": "Dashboard", "sales": 150 }
revenue conjunto de dados (2 linhas):
{ "product": "Widget", "revenue": 5000 }
{ "product": "Gadget", "revenue": 8000 }
Executando esta consulta:
source sales | orderby product
| stitch (source revenue | orderby product) into combined_data
Resulta em:
{ "product": "Widget", "sales": 100, "combined_data": { "product": "Widget", "revenue": 5000 } }
{ "product": "Gadget", "sales": 200, "combined_data": { "product": "Gadget", "revenue": 8000 } }
{ "product": "Dashboard", "sales": 150, "combined_data": { "product": "Dashboard", "revenue": null } }
stitch Observações de uso
-
As linhas devem se correlacionar logicamente para que a costura produza resultados significativos. Certifique-se de que as linhas de ambos os conjuntos de dados representem as mesmas entidades e estejam na mesma ordem. Por exemplo, se o campo
productno conjunto de dadossalesnão corresponder ao campoproductno conjunto de dadosrevenuepara as linhas correspondentes, a costura não funcionará como esperado. -
Se os conjuntos de dados diferirem na contagem de linhas, o resultado incluirá
nullvalores para dados ausentes no conjunto de dados mais curto.
top
Nenhuma variação de agrupamento: Limita as linhas retornadas a um número especificado e ordena o resultado por um conjunto de expressões.
order_direction := "descending"/"ascending" according to top/bottom
top <limit> <result_expression1> [as <alias>] [, <result_expression2> [as <alias2>], ...] by <orderby_expression> [as alias>]
Por exemplo, a consulta a seguir:
top 5 $m.severity as $d.log_severity by $d.duration
Resultará em registros do seguinte formato:
[
{ "log_severity": "Warning", "duration": 2000 },
{ "log_severity": "Debug", "duration": 1000 }
...
]
Variação de agrupamento: Limita as linhas retornadas a um número especificado e as agrupa por um conjunto de expressões de agregação e as ordena por um conjunto de expressões.
order_direction := "descending"/"ascending" according to top/bottom
top <limit> <(groupby_expression1|aggregate_function1)> [as <alias>] [, <(groupby_expression2|aggregate_function2)> [as <alias2>], ...] by <(groupby_expression1|aggregate_function1)> [as <alias>]
Por exemplo, a consulta a seguir:
top 10 $m.severity, count() as $d.number_of_severities by avg($d.duration) as $d.avg_duration
Resultará em registros do seguinte formato:
[
{ "severity": "Debug", "number_of_severities": 10, avg_duration: 2000 }
{ "severity": "Warning", "number_of_severities": 50, avg_duration: 1000 },
...
]
Você pode aplicar uma função de agregação.
union
O comando union concatena os resultados de dois ou mais conjuntos de dados em um único conjunto de dados. Isso permite que os usuários combinem resultados de várias consultas em um único conjunto de dados. Um conjunto de dados pode
ser um conjunto de resultados canalizado para o comando union e, em seguida, concatenado com outro conjunto de dados.
Use a união quando precisar anexar linhas de um conjunto de dados a outro.
Ao processar grandes conjuntos de dados, para otimizar o desempenho, considere usar filter para limitar as linhas de cada conjunto de dados antes de usar union.
Os usuários estão limitados a um máximo de 10 comandos union por consulta para dados Insights prioritários. Não há limite para outros dados.
Como o site union difere de join
-
unioncombina conjuntos de resultados anexando linhas de um conjunto de dados a outro. Ele não mescla ou compara colunas de vários documentos. -
joincorresponde e combina colunas de duas tabelas com base em uma condição, criando linhas que contêm dados de ambas as tabelas.
<query> | union <query>
Exemplo de combinação de 2 conjuntos de dados
Você tem esses dois conjuntos de dados:
Registros para Team 58942
{ "id": "111", "name": "John" , "team.id": "58942" }
{ "id": "222", "name": "Emily", "team.id": "58942" }
{ "id": "333", "name": "Alice", "team.id": "58942" }
Registros para Team 98361
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z", "team.id": "98361" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
E você deseja combiná-los em um único conjunto de dados. Você pode fazer isso usando union.
source logs(teamId=58942) | union logs(teamId=98361)
A consulta processa os dois conjuntos de dados:
source logs(teamId=58942): Recupera todos os documentos paraTeam 58942union logs (teamID=98361): Anexa o conjunto de dadosTeam 98361ao conjunto de dadosTeam 58942
Isso resultará no seguinte conjunto de dados:
{ "id": "111", "name": "John" , "team.id": "58942" }
{ "id": "222", "name": "Emily", "team.id": "58942" }
{ "id": "333", "name": "Alice", "team.id": "58942" }
{ "userid": "111", "timestamp": "2022-01-01T12:00:00Z", "team.id": "98361" }
{ "userid": "111", "timestamp": "2022-01-01T12:30:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }
{ "userid": "222", "timestamp": "2022-01-01T13:00:00Z", "team.id": "98361" }