Share via


Esercitazione: Rilevare e analizzare anomalie usando le funzionalità di Machine Learning KQL in Monitoraggio di Azure

La Linguaggio di query Kusto (KQL) include operatori di Machine Learning, funzioni e plug-in per l'analisi delle serie temporali, il rilevamento anomalie, la previsione e l'analisi della causa radice. Usare queste funzionalità KQL per eseguire l'analisi avanzata dei dati in Monitoraggio di Azure senza il sovraccarico dell'esportazione dei dati negli strumenti di Machine Learning esterni.

In questa esercitazione verranno illustrate le procedure per:

  • Creare una serie temporale
  • Identificare le anomalie in una serie temporale
  • Modificare le impostazioni di rilevamento anomalie per perfezionare i risultati
  • Analizzare la causa radice delle anomalie

Nota

Questa esercitazione fornisce collegamenti a un ambiente demo di Log Analytics in cui è possibile eseguire gli esempi di query KQL. È tuttavia possibile implementare le stesse query e entità KQL in tutti gli strumenti di Monitoraggio di Azure che usano KQL.

Prerequisiti

Autorizzazioni necessarie

È necessario disporre Microsoft.OperationalInsights/workspaces/query/*/read delle autorizzazioni per le aree di lavoro Log Analytics che si esegue la query, come indicato dal ruolo predefinito lettore di Log Analytics, ad esempio.

Creare una serie temporale

Usare l'operatore KQL make-series per creare una serie temporale.

Verrà creata una serie temporale basata sui log nella tabella Utilizzo, che contiene informazioni sulla quantità di dati inseriti ogni ora in un'area di lavoro, inclusi i dati fatturabili e non fatturabili.

Questa query usa make-series per graficore la quantità totale di dati fatturabili inseriti da ogni tabella nell'area di lavoro ogni giorno, negli ultimi 21 giorni:

Fare clic per eseguire la query

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

Nel grafico risultante è possibile visualizzare chiaramente alcune anomalie, ad esempio nei AzureDiagnostics tipi di dati e SecurityEvent :

GIF animata che mostra un grafico dei dati totali inseriti da ogni tabella nell'area di lavoro ogni giorno, oltre 21 giorni. Il cursore passa per evidenziare tre anomalie di utilizzo nel grafico.

Verrà quindi usata una funzione KQL per elencare tutte le anomalie in una serie temporale.

Nota

Per altre informazioni sulla sintassi e sull'utilizzo make-series , vedere operatore make-series.

Trovare anomalie in una serie temporale

La series_decompose_anomalies() funzione accetta una serie di valori come input ed estrae anomalie.

Si assegna il set di risultati della query della serie temporale come input alla series_decompose_anomalies() funzione:

Fare clic per eseguire la query

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

Questa query restituisce tutte le anomalie di utilizzo per tutte le tabelle negli ultimi tre settimane:

Screenshot di una tabella che mostra un elenco di anomalie in uso per tutte le tabelle nell'area di lavoro.

Esaminando i risultati della query, è possibile notare che la funzione:

  • Calcola un utilizzo giornaliero previsto per ogni tabella.
  • Confronta l'utilizzo giornaliero effettivo con l'utilizzo previsto.
  • Assegna un punteggio anomalie a ogni punto dati, che indica l'estensione della deviazione dell'utilizzo effettivo dall'utilizzo previsto.
  • Identifica anomalie positive () e negative (1-1) in ogni tabella.

Nota

Per altre informazioni sulla sintassi e sull'utilizzo series_decompose_anomalies() , vedere series_decompose_anomalies().

Modificare le impostazioni di rilevamento anomalie per perfezionare i risultati

È consigliabile esaminare i risultati iniziali delle query e apportare modifiche alla query, se necessario. I outlier nei dati di input possono influire sull'apprendimento della funzione e potrebbe essere necessario modificare le impostazioni di rilevamento anomalie della funzione per ottenere risultati più accurati.

Filtrare i risultati della series_decompose_anomalies() query per le anomalie nel AzureDiagnostics tipo di dati:

Tabella che mostra i risultati della query di rilevamento anomalie, filtrata per i risultati dal tipo di dati Diagnostica di Azure.

I risultati mostrano due anomalie il 14 giugno e il 15 giugno. Confrontare questi risultati con il grafico dalla prima make-series query, dove è possibile visualizzare altre anomalie il 27 maggio e 28:

Screenshot che mostra un grafico dei dati totali inseriti dalla tabella Diagnostica di Azure con anomalie evidenziate.

La differenza nei risultati si verifica perché i series_decompose_anomalies() punteggi delle funzioni sono anomalie relative al valore di utilizzo previsto, che la funzione calcola in base all'intervallo completo di valori nella serie di input.

Per ottenere risultati più raffinati dalla funzione, escludere l'utilizzo del 15 giugno, ovvero un outlier rispetto agli altri valori della serie, dal processo di apprendimento della funzione.

La sintassi della series_decompose_anomalies() funzione è:

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

Test_points specifica il numero di punti alla fine della serie da escludere dal processo di apprendimento (regressione).

Per escludere l'ultimo punto dati, impostare Test_points su 1:

Fare clic per eseguire la query

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

Filtrare i risultati per il AzureDiagnostics tipo di dati:

Tabella che mostra i risultati della query di rilevamento anomalie modificata, filtrata per i risultati dal tipo di dati Diagnostica di Azure. I risultati mostrano ora le stesse anomalie del grafico creato all'inizio dell'esercitazione.

Tutte le anomalie nel grafico della prima make-series query vengono ora visualizzate nel set di risultati.

Analizzare la causa radice delle anomalie

Il confronto dei valori previsti con valori anomali consente di comprendere la causa delle differenze tra i due set.

Il plug-in KQL diffpatterns() confronta due set di dati della stessa struttura e trova modelli che caratterizzano le differenze tra i due set di dati.

Questa query confronta AzureDiagnostics l'utilizzo del 15 giugno, l'outlier estremo nell'esempio, con l'utilizzo della tabella in altri giorni:

Fare clic per eseguire la query

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

La query identifica ogni voce nella tabella come si verifica in AnomalyDate (15 giugno) o OtherDates. Il diffpatterns() plug-in suddivide quindi questi set di dati, denominati A (OtherDates nell'esempio) e B (AnomalyDate nell'esempio) e restituisce alcuni modelli che contribuiscono alle differenze nei due set:

Screenshot che mostra una tabella con tre righe. Ogni riga mostra una differenza tra l'uso anomalo e l'utilizzo della baseline.

Esaminando i risultati della query, è possibile visualizzare le differenze seguenti:

  • Sono presenti 24.892.147 istanze di inserimento dalla risorsa CH1-GEARAMAAKS in tutti gli altri giorni nell'intervallo di tempo di query e nessun inserimento di dati da questa risorsa il 15 giugno. I dati della risorsa CH1-GEARAMAAKS sono pari al 73,36% dell'inserimento totale negli altri giorni nell'intervallo di tempo di query e al 0% dell'inserimento totale del 15 giugno.
  • Sono presenti 2.168.448 istanze di inserimento dalla risorsa NSG-TESTSQLMI519 in tutti gli altri giorni nell'intervallo di tempo di query e 110.544 istanze di inserimento da questa risorsa il 15 giugno. I dati della risorsa NSG-TESTSQLMI519 sono pari al 6,39% dell'inserimento totale in altri giorni nell'intervallo di tempo di query e al 25,61% dell'inserimento il 15 giugno.

Si noti che, in media, sono presenti 108.422 istanze di inserimento dalla risorsa NSG-TESTSQLMI519 durante i 20 giorni che costituiscono l'altro periodo (dividere 2.168.448 per 20). Pertanto, l'inserimento dalla risorsa NSG-TESTSQLMI519 il 15 giugno non è significativamente diverso dall'inserimento da questa risorsa in altri giorni. Tuttavia, poiché non esiste inserimento da CH1-GEARAMAAKS il 15 giugno, l'inserimento da NSG-TESTSQLMI519 costituisce una percentuale significativamente maggiore dell'inserimento totale sulla data anomalie rispetto ad altri giorni.

La colonna PercentDiffAB mostra la differenza di punti percentuale assoluta tra A e B (|PercentA - PercentB|), ovvero la misura principale della differenza tra i due set. Per impostazione predefinita, il diffpatterns() plug-in restituisce la differenza di oltre il 5% tra i due set di dati, ma è possibile modificare questa soglia. Ad esempio, per restituire solo differenze del 20% o più tra i due set di dati, è possibile impostare | evaluate diffpatterns(AnomalyDate, "OtherDates", "AnomalyDate", "~", 0.20) nella query precedente. La query restituisce ora un solo risultato:

Screenshot che mostra una tabella con una riga che presenta una differenza tra l'uso anomalo e l'utilizzo della baseline. Questa volta, la query non ha restituito differenze di meno del 20% tra i due set di dati.

Nota

Per altre informazioni sulla sintassi e sull'utilizzo diffpatterns() , vedere plug-in dei modelli di diff.

Passaggi successivi

Altre informazioni su: