Share via


Tutorial: Detetar e analisar anomalias com as capacidades de machine learning KQL no Azure Monitor

O Linguagem de Pesquisa Kusto (KQL) inclui operadores de machine learning, funções e plug-ins para análise de série temporal, deteção de anomalias, previsão e análise da causa raiz. Utilize estas capacidades de KQL para realizar análises de dados avançadas no Azure Monitor sem a sobrecarga da exportação de dados para ferramentas externas de machine learning.

Neste tutorial, ficará a saber como:

  • Criar uma série temporal
  • Identificar anomalias numa série temporal
  • Ajustar as definições de deteção de anomalias para refinar resultados
  • Analisar a causa principal das anomalias

Nota

Este tutorial fornece ligações para um ambiente de demonstração do Log Analytics no qual pode executar os exemplos de consulta KQL. No entanto, pode implementar as mesmas consultas E principais KQL em todas as ferramentas do Azure Monitor que utilizam KQL.

Pré-requisitos

Permissões necessárias

Tem de ter Microsoft.OperationalInsights/workspaces/query/*/read permissões para as áreas de trabalho do Log Analytics que consulta, conforme fornecido pela função incorporada leitor do Log Analytics, por exemplo.

Criar uma série temporal

Utilize o operador KQL make-series para criar uma série temporal.

Vamos criar uma série temporal com base em registos na tabela Utilização, que contém informações sobre a quantidade de dados que cada tabela numa área de trabalho ingere a cada hora, incluindo dados faturáveis e não faturáveis.

Esta consulta utiliza make-series para traçar a quantidade total de dados faturáveis ingeridos por cada tabela na área de trabalho todos os dias, nos últimos 21 dias:

Clique para executar a consulta

let starttime = 21d; // The start date of the time series, counting back from the current date
let endtime = 0d; // The end date of the time series, counting back from the current date
let timeframe = 1d; // How often to sample data
Usage // The table we’re analyzing
| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime))) // Time range for the query, beginning at 12:00 AM of the first day and ending at 12:00 AM of the last day in the time range
| where IsBillable == "true" // Include only billable data in the result set
| make-series ActualUsage=sum(Quantity) default = 0 on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime)) step timeframe by DataType // Creates the time series, listed by data type 
| render timechart // Renders results in a timechart

No gráfico resultante, pode ver claramente algumas anomalias , por exemplo, nos AzureDiagnostics tipos de dados e SecurityEvent :

Um GIF animado que mostra um gráfico do total de dados ingeridos por cada tabela na área de trabalho todos os dias, ao longo de 21 dias. O cursor move-se para realçar três anomalias de utilização no gráfico.

Em seguida, vamos utilizar uma função KQL para listar todas as anomalias numa série temporal.

Nota

Para obter mais informações sobre make-series sintaxe e utilização, veja operador make-series.

Localizar anomalias numa série temporal

A series_decompose_anomalies() função utiliza uma série de valores como entrada e extrai anomalias.

Vamos dar o conjunto de resultados da nossa consulta de série temporal como entrada para a series_decompose_anomalies() função:

Clique para executar a consulta

let starttime = 21d; // Start date for the time series, counting back from the current date
let endtime = 0d; // End date for the time series, counting back from the current date
let timeframe = 1d; // How often to sample data
Usage // The table we’re analyzing
| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime))) // Time range for the query, beginning at 12:00 AM of the first day and ending at 12:00 AM of the last day in the time range
| where IsBillable == "true" // Includes only billable data in the result set
| make-series ActualUsage=sum(Quantity) default = 0 on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime)) step timeframe by DataType // Creates the time series, listed by data type
| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(ActualUsage) // Scores and extracts anomalies based on the output of make-series 
| mv-expand ActualUsage to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double),AnomalyScore to typeof(double), ExpectedUsage to typeof(long) // Expands the array created by series_decompose_anomalies()
| where Anomalies != 0  // Returns all positive and negative deviations from expected usage
| project TimeGenerated,ActualUsage,ExpectedUsage,AnomalyScore,Anomalies,DataType // Defines which columns to return 
| sort by abs(AnomalyScore) desc // Sorts results by anomaly score in descending ordering

Esta consulta devolve todas as anomalias de utilização de todas as tabelas nas últimas três semanas:

Uma captura de ecrã de uma tabela a mostrar uma lista de anomalias na utilização de todas as tabelas na área de trabalho.

Olhando para os resultados da consulta, pode ver que a função:

  • Calcula uma utilização diária esperada para cada tabela.
  • Compara a utilização diária real com a utilização esperada.
  • Atribui uma classificação de anomalia a cada ponto de dados, indicando a extensão do desvio da utilização real da utilização esperada.
  • Identifica anomalias positivas (1) e negativas (-1) em cada tabela.

Nota

Para obter mais informações sobre series_decompose_anomalies() sintaxe e utilização, veja series_decompose_anomalies().

Ajustar as definições de deteção de anomalias para refinar resultados

É uma boa prática rever os resultados iniciais da consulta e fazer ajustes à consulta, se necessário. Os valores atípicos nos dados de entrada podem afetar a aprendizagem da função e poderá ter de ajustar as definições de deteção de anomalias da função para obter resultados mais precisos.

Filtre os resultados da series_decompose_anomalies() consulta para obter anomalias no AzureDiagnostics tipo de dados:

Uma tabela que mostra os resultados da consulta de deteção de anomalias, filtrada para obter resultados do tipo de dados Diagnóstico do Azure.

Os resultados mostram duas anomalias nos dias 14 de junho e 15 de junho. Compare estes resultados com o gráfico da nossa primeira make-series consulta, onde pode ver outras anomalias nos dias 27 e 28 de maio:

Captura de ecrã a mostrar um gráfico do total de dados ingeridos pela tabela Diagnóstico do Azure com anomalias realçadas.

A diferença nos resultados ocorre porque a series_decompose_anomalies() função classifica anomalias relativamente ao valor de utilização esperado, que a função calcula com base no intervalo completo de valores na série de entrada.

Para obter resultados mais refinados da função, exclua a utilização no dia 15 de junho - que é um valor mais atípico em comparação com os outros valores da série - do processo de aprendizagem da função.

A sintaxe da series_decompose_anomalies() função é:

series_decompose_anomalies (Series[Threshold,Seasonality,Trend,Test_points,AD_method,Seasonality_threshold])

Test_points especifica o número de pontos no final da série a excluir do processo de aprendizagem (regressão).

Para excluir o último ponto de dados, defina Test_points como 1:

Clique para executar a consulta

let starttime = 21d; // Start date for the time series, counting back from the current date
let endtime = 0d; // End date for the time series, counting back from the current date
let timeframe = 1d; // How often to sample data
Usage // The table we’re analyzing
| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime))) // Time range for the query, beginning at 12:00 AM of the first day and ending at 12:00 AM of the last day in the time range
| where IsBillable == "true" // Includes only billable data in the result set
| make-series ActualUsage=sum(Quantity) default = 0 on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime)) step timeframe by DataType // Creates the time series, listed by data type
| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(ActualUsage,1.5,-1,'avg',1) // Scores and extracts anomalies based on the output of make-series, excluding the last value in the series - the Threshold, Seasonality, and Trend input values are the default values for the function 
| mv-expand ActualUsage to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double),AnomalyScore to typeof(double), ExpectedUsage to typeof(long) // Expands the array created by series_decompose_anomalies()
| where Anomalies != 0  // Returns all positive and negative deviations from expected usage
| project TimeGenerated,ActualUsage,ExpectedUsage,AnomalyScore,Anomalies,DataType // Defines which columns to return 
| sort by abs(AnomalyScore) desc // Sorts results by anomaly score in descending ordering

Filtre os resultados do AzureDiagnostics tipo de dados:

Uma tabela que mostra os resultados da consulta de deteção de anomalias modificada, filtrada para obter resultados do tipo de dados Diagnóstico do Azure. Os resultados mostram agora as mesmas anomalias que o gráfico criado no início do tutorial.

Todas as anomalias no gráfico da nossa primeira make-series consulta aparecem agora no conjunto de resultados.

Analisar a causa principal das anomalias

Comparar valores esperados com valores anómalos ajuda-o a compreender a causa das diferenças entre os dois conjuntos.

O plug-in KQL diffpatterns() compara dois conjuntos de dados da mesma estrutura e encontra padrões que caracterizam as diferenças entre os dois conjuntos de dados.

Esta consulta compara a AzureDiagnostics utilização no dia 15 de junho, o valor mais atípico no nosso exemplo, com a utilização da tabela noutros dias:

Clique para executar a consulta

let starttime = 21d; // Start date for the time series, counting back from the current date
let endtime = 0d; // End date for the time series, counting back from the current date
let anomalyDate = datetime_add('day',-1, make_datetime(startofday(ago(endtime)))); // Start of day of the anomaly date, which is the last full day in the time range in our example (you can replace this with a specific hard-coded anomaly date)
AzureDiagnostics	
| extend AnomalyDate = iff(startofday(TimeGenerated) == anomalyDate, "AnomalyDate", "OtherDates") // Adds calculated column called AnomalyDate, which splits the result set into two data sets – AnomalyDate and OtherDates
| where TimeGenerated between (startofday(ago(starttime))..startofday(ago(endtime))) // Defines the time range for the query
| project AnomalyDate, Resource // Defines which columns to return
| evaluate diffpatterns(AnomalyDate, "OtherDates", "AnomalyDate") // Compares usage on the anomaly date with the regular usage pattern

A consulta identifica cada entrada na tabela como ocorrendo em AnomalyDate (15 de junho) ou OtherDates. Em diffpatterns() seguida, o plug-in divide estes conjuntos de dados - denominados A (OtherDates no nosso exemplo) e B (AnomalyDate no nosso exemplo) - e devolve alguns padrões que contribuem para as diferenças nos dois conjuntos:

Captura de ecrã a mostrar uma tabela com três linhas. Cada linha mostra uma diferença entre a utilização na utilização anómalo e a utilização da linha de base.

Ao analisar os resultados da consulta, pode ver as seguintes diferenças:

  • Existem 24 892 147 instâncias de ingestão do recurso CH1-GEARAMAAKS em todos os outros dias no intervalo de tempo da consulta e nenhuma ingestão de dados deste recurso no dia 15 de junho. Os dados do recurso CH1-GEARAMAAKS representam 73,36% da ingestão total noutros dias no intervalo de tempo da consulta e 0% da ingestão total em 15 de junho.
  • Existem 2.168.448 instâncias de ingestão do recurso NSG-TESTSQLMI519 em todos os outros dias no intervalo de tempo da consulta e 110.544 instâncias de ingestão deste recurso no dia 15 de junho. Os dados do recurso NSG-TESTSQLMI519 representam 6,39% do total da ingestão noutros dias no intervalo de tempo da consulta e 25,61% da ingestão em 15 de junho.

Tenha em atenção que, em média, existem 108.422 instâncias de ingestão do recurso NSG-TESTSQLMI519 durante os 20 dias que compõem o período de outros dias (divida 2.168.448 por 20). Por conseguinte, a ingestão do recurso NSG-TESTSQLMI519 a 15 de Junho não é significativamente diferente da ingestão deste recurso noutros dias. No entanto, como não existe ingestão de CH1-GEARAMAAKS a 15 de Junho, a ingestão de NSG-TESTSQLMI519 constitui uma percentagem significativamente maior da ingestão total na data da anomalia em comparação com outros dias.

A coluna PercentDiffAB mostra a diferença absoluta de pontos percentuais entre A e B (|PercentA - PercentB|), que é a principal medida da diferença entre os dois conjuntos. Por predefinição, o diffpatterns() plug-in devolve uma diferença superior a 5% entre os dois conjuntos de dados, mas pode ajustar este limiar. Por exemplo, para devolver apenas diferenças de 20% ou mais entre os dois conjuntos de dados, pode definir | evaluate diffpatterns(AnomalyDate, "OtherDates", "AnomalyDate", "~", 0.20) na consulta acima. A consulta devolve agora apenas um resultado:

Captura de ecrã a mostrar uma tabela com uma linha que apresenta uma diferença entre a utilização na utilização anómalo e a utilização da linha de base. Desta vez, a consulta não devolveu diferenças inferiores a 20% entre os dois conjuntos de dados.

Nota

Para obter mais informações sobre diffpatterns() sintaxe e utilização, veja plug-in de padrões difusos.

Passos seguintes

Saiba mais sobre: