Começar pela população que a decisão exige
Antes de escrever a consulta, define o que tem de estar representado: serviços, ambientes, versões e intervalo de observação. Num exercício de release com API e Batch, uma linha saudável de API não representa o conjunto. Guarda uma lista independente dos deployments esperados e compara-a com a telemetria recebida. ExpectedDeployments à esquerda de um leftanti sobre Heartbeats identifica os deployments sem correspondência na janela escolhida. O resultado é uma lista de lacunas de evidência, não um diagnóstico automático de falha. Para cada lacuna, procura o responsável pela origem, confirma destino e filtros e regista o prazo para esclarecer a situação. Esta preparação evita que a própria consulta defina silenciosamente a população que depois declara saudável. A decisão deve explicar tanto os serviços observados como os que continuam sem cobertura confirmada.
Controlar a cardinalidade antes de correlacionar
Dois eventos podem partilhar OperationId sem serem duplicados. Um pagamento tem accepted e settled; ambos são necessários à análise do percurso. O join predefinido usa innerunique e elimina chaves repetidas à esquerda, pelo que pode perder um desses eventos. Não prometas qual deles sobrevive. Se a tabela de owners tiver exatamente uma linha correspondente, join kind=inner conserva os dois. Se tiver duas, a correlação pode multiplicar resultados. Por isso, escreve as expectativas de cardinalidade para cada lado e compara contagens antes e depois. Ordenar a entrada ou mudar uma hint de execução não resolve uma escolha errada de semântica. Também não uses inner para medir cobertura de deployments: os que não têm correspondência desaparecem. Escolhe a operação em função da pergunta e conserva separadamente a evidência de itens sem correspondência.
Conservar o estado da linha mais recente
O painel de deployments precisa frequentemente do último estado e do momento em que foi observado. max(TimeGenerated) calcula um valor temporal, mas não escolhe por si o State correspondente. Combinar esse máximo com um estado arbitrário pode criar uma linha que nunca existiu na origem. Usa summarize arg_max(TimeGenerated, State) by DeploymentId quando queres o estado da linha que maximiza o tempo. No exercício, os timestamps são únicos por deployment, evitando ambiguidade de empate. Em dados reais, define uma regra quando eventos diferentes partilham timestamp e confirma a semântica do campo temporal. Um estado recente também não elimina a necessidade de identificar ambiente e candidato. No relatório para RUN, apresenta a identidade completa e a janela usada, para que ninguém confunda o último evento de teste com a situação de produção.
Interpretar o tipo antes de interpretar o valor
Um fornecedor pode enviar um objeto JSON cujo campo detail é outra string JSON. Depois de parse_json(Payload), esse campo é dynamic, mas ainda contém texto. Voltar a chamar parse_json diretamente sobre o campo dynamic conserva o valor tal como está. A expressão parse_json(tostring(d.detail)).code converte primeiro o campo para texto e interpreta depois o JSON interno. Este detalhe aparece em investigação de logs quando uma coluna parece conter a informação, mas a extração devolve um valor inesperado. Antes de alterar alertas, observa uma amostra autorizada e confirma o contrato do produtor. Distingue JSON malformado, propriedade ausente e string interna ainda não interpretada. O exercício assume JSON válido nas duas camadas; não promete reparar formatos inválidos nem demonstrar que todos os eventos seguem o mesmo contrato.
Tratar avisos como parte do resultado
Uma consulta pode devolver linhas úteis e continuar incompleta para a decisão. No mesmo database existente, union isfuzzy=true pode resolver ApiLogs, não resolver BatchLogs e devolver dados com um aviso. A tolerância à resolução parcial não é uma prova de ausência de erros no serviço Batch. Também não suprime indiscriminadamente falhas posteriores da consulta. Regista o aviso juntamente com as fontes esperadas e efetivamente observadas. Se ambas forem obrigatórias, a promoção fica dependente de recuperar a evidência em falta. Uma fonte alternativa só serve se estiver aprovada para o critério e corresponder ao mesmo candidato e intervalo. Evita consultas com listas de fontes implícitas que mudem o âmbito sem revisão. Uma equipa de projeto deve conseguir explicar que dependência está aberta, quem a resolve e que consequência tem na janela de entrega.
Separar intervalos vazios de atividade nula
bin(TimeGenerated, 5m) agrupa eventos em intervalos; não cria linhas para períodos sem observações. Acrescentar intervalos ao eixo pode facilitar leitura, mas um zero de apresentação não demonstra que a recolha estava completa. Quando o coletor está por confirmar, identifica a lacuna. A escolha de fronteiras também importa: between inclui os dois extremos. Dois relatórios consecutivos podem contar o mesmo evento no ponto de encontro. Usar TimeGenerated >= Start and TimeGenerated < End atribui esse evento à janela seguinte, mantendo cada início incluído. Esta convenção resolve a sobreposição temporal, não duplicados existentes na origem nem eventos que chegaram tarde. Num handover, regista timezone, fronteiras, momento de extração e estado de cobertura. Assim, diferenças entre relatórios podem ser investigadas sem assumir imediatamente uma alteração no comportamento do serviço.
Escolher entre estimativa e contagem exata
Para explorar milhões de identificadores, dcount oferece uma estimativa com compromissos de precisão e recursos. A existência de modos exatos para conjuntos pequenos não garante exatidão em qualquer dimensão. Se o requisito exige contar exatamente os CustomerId de uma extração fixa, primeiro define a população, o tratamento de valores vazios e a completude da consulta. No exercício, todos os IDs são não vazios e a execução cabe nos limites aprovados; distinct CustomerId seguido de count conta o conjunto observado. Não substituas este processo pela média arredondada de várias estimativas. Também não confundas eventos com clientes: um cliente pode ter muitas linhas. Finalmente, um cálculo exato sobre uma extração incompleta continua sem representar todos os clientes reais. Comunica o âmbito junto do número e conserva os critérios usados para produzir a extração.
Exercício guiado e decisão de release
No exemplo abaixo, a lista esperada contém D1 e D2, mas só D1 tem heartbeat. Prevê o resultado da consulta antes de a executar num ambiente de aprendizagem autorizado: D2 deve aparecer como lacuna de evidência. O exemplo é estático e não foi executado num motor Kusto. Depois analisa o caso final: API está verde, BatchLogs não foi resolvida e a política exige os dois serviços. Escreve uma nota com a decisão de reter a promoção, o responsável pela investigação e a evidência necessária para reconsiderar. Não declares Batch avariado apenas porque faltam logs. Uma alternativa atual e aprovada pode resolver a lacuna; um resultado antigo não satisfaz o critério. Termina comparando população esperada, linhas observadas, avisos e fronteiras temporais antes de interpretar qualquer cor do dashboard como autorização de entrega.
// Static fictional exercise; not executed in a Kusto engine.
let ExpectedDeployments = datatable(DeploymentId:string) ["D1", "D2"];
let ObservedHeartbeats = datatable(DeploymentId:string) ["D1"];
ExpectedDeployments
| join kind=leftanti ObservedHeartbeats on DeploymentId
// Predicted result: D2. Missing evidence, not a confirmed service failure.
API e Batch são obrigatórios para aceitar uma release. A consulta só mostra API e avisa sobre BatchLogs: o resultado não demonstra cobertura suficiente.
Armadilhas comuns
Deduplicar eventos legítimos, esconder deployments num inner join, preencher lacunas como sucesso e atribuir exatidão universal a dcount.
Tópicos relacionados: Critérios de aceitação de releases · Qualidade e contratos de telemetria · Investigação de incidentes e handover
Uma consulta útil conserva a população necessária à decisão e distingue resultado, cobertura, precisão e incerteza.
Referência: innerunique join · AZ-400 objectives 2026-07-27