Kurz: Detekce a analýza anomálií pomocí funkcí strojového učení KQL ve službě Azure Monitor

Dotazovací jazyk Kusto (KQL) zahrnuje operátory strojového učení, funkce a moduly plug-in pro analýzu časových řad, detekci anomálií, prognózování a analýzu původní příčiny. Pomocí těchto funkcí KQL můžete provádět pokročilou analýzu dat ve službě Azure Monitor bez režie při exportu dat do externích nástrojů strojového učení.

V tomto kurzu se naučíte:

  • Vytvoření časové řady
  • Identifikace anomálií v časové řadě
  • Vylepšení nastavení detekce anomálií za účelem upřesnění výsledků
  • Analýza původní příčiny anomálií

Poznámka:

Tento kurz obsahuje odkazy na ukázkové prostředí Log Analytics, ve kterém můžete spustit příklady dotazů KQL. Data v ukázkovém prostředí jsou dynamická, takže výsledky dotazu nejsou stejné jako výsledky dotazu uvedené v tomto článku. Můžete ale implementovat stejné dotazy a objekty zabezpečení KQL ve vlastním prostředí a všechny nástroje azure Monitoru, které používají KQL.

Požadavky

Požadována oprávnění

Musíte mít Microsoft.OperationalInsights/workspaces/query/*/read oprávnění k pracovním prostorům služby Log Analytics, které dotazujete, jak poskytuje integrovaná role Čtenář log Analytics, například.

Vytvoření časové řady

K vytvoření časové řady použijte operátor KQL make-series .

Pojďme vytvořit časovou řadu na základě protokolů v tabulce Využití, která obsahuje informace o tom, kolik dat každá tabulka v pracovním prostoru ingestuje každou hodinu, včetně fakturovatelných a nefakturovatelných dat.

Tento dotaz používá make-series k vytvoření grafu celkového množství fakturovatelných dat přijatých každou tabulkou v pracovním prostoru každý den za posledních 21 dnů:

Kliknutím spustíte dotaz.

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

Ve výsledném grafu můžete jasně vidět některé anomálie – například v AzureDiagnostics datových typech:SecurityEvent

Animovaný obrázek GIF zobrazující graf celkových dat přijatých každou tabulkou v pracovním prostoru každý den, více než 21 dnů. Kurzor se přesune a zvýrazní tři anomálie využití v grafu.

V dalším kroku použijeme funkci KQL k výpisu všech anomálií v časové řadě.

Poznámka:

Další informace o make-series syntaxi a použití najdete v tématu operátor make-series.

Vyhledání anomálií v časové řadě

Funkce series_decompose_anomalies() přebírá jako vstup řadu hodnot a extrahuje anomálie.

Pojďme dát sadě výsledků dotazu časové řady jako vstup do series_decompose_anomalies() funkce:

Kliknutím spustíte dotaz.

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

Tento dotaz vrátí všechny anomálie využití pro všechny tabulky za poslední tři týdny:

Snímek obrazovky tabulky zobrazující seznam anomálií, které se ve všech tabulkách v pracovním prostoru používá

Když se podíváte na výsledky dotazu, uvidíte, že funkce:

  • Vypočítá očekávané denní využití pro každou tabulku.
  • Porovná skutečné denní využití s očekávaným využitím.
  • Přiřadí každému datovému bodu skóre anomálií, které označuje rozsah odchylky skutečného využití od očekávaného využití.
  • Identifikuje kladné () a záporné (1-1) anomálie v každé tabulce.

Poznámka:

Další informace o series_decompose_anomalies() syntaxi a použití najdete v tématu series_decompose_anomalies().

Vylepšení nastavení detekce anomálií za účelem upřesnění výsledků

Je vhodné zkontrolovat počáteční výsledky dotazu a v případě potřeby ho upravit. Odlehlé hodnoty ve vstupních datech můžou ovlivnit učení funkce a možná budete muset upravit nastavení detekce anomálií funkce, abyste získali přesnější výsledky.

Vyfiltrujte výsledky series_decompose_anomalies() dotazu na anomálie v datovém AzureDiagnostics typu:

Tabulka zobrazující výsledky dotazu detekce anomálií filtrovaná pro výsledky z datového typu Azure Diagnostics.

Výsledky zobrazují dvě anomálie 14. června a 15. června. Porovnejte tyto výsledky s grafem z našeho prvního make-series dotazu, kde můžete vidět další anomálie 27. května a 28:

Snímek obrazovky znázorňující graf celkových ingestovaných dat tabulkou Azure Diagnostics se zvýrazněnými anomáliemi

Rozdíl ve výsledcích nastane, protože series_decompose_anomalies() funkce vyhodnotí anomálie vzhledem k očekávané hodnotě využití, kterou funkce vypočítá na základě úplného rozsahu hodnot ve vstupní řadě.

Pokud chcete z funkce získat přesnější výsledky, vylučte z procesu učení funkce použití v 15. červnu , což je odlehlé hodnoty v porovnání s ostatními hodnotami v řadě.

Syntaxe series_decompose_anomalies() funkce je:

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

Test_points určuje počet bodů na konci řady, které se mají vyloučit z procesu učení (regrese).

Pokud chcete vyloučit poslední datový bod, nastavte Test_points hodnotu 1:

Kliknutím spustíte dotaz.

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

Vyfiltrujte výsledky pro AzureDiagnostics datový typ:

Tabulka zobrazující výsledky upraveného dotazu detekce anomálií filtrované pro výsledky z datového typu Azure Diagnostics. Výsledky teď zobrazují stejné anomálie jako graf vytvořený na začátku kurzu.

Všechny anomálie v grafu z prvního make-series dotazu se teď zobrazují v sadě výsledků.

Analýza původní příčiny anomálií

Porovnání očekávaných hodnot s neobvyklými hodnotami vám pomůže pochopit příčinu rozdílů mezi těmito dvěma sadami.

Modul plug-in KQL diffpatterns() porovnává dvě datové sady stejné struktury a najde vzory, které charakterizují rozdíly mezi těmito dvěma datovými sadami.

Tento dotaz porovnává AzureDiagnostics využití 15. června, extrémní odlehlé hodnoty v našem příkladu s využitím tabulky v jiných dnech:

Kliknutím spustíte dotaz.

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

Dotaz identifikuje každou položku v tabulce jako výskyt v anomáliích (červen 15) nebo OtherDates. Modul diffpatterns() plug-in pak tyto datové sady rozdělí – označované jako A (JinéDates v našem příkladu) a B (anomálieDate v našem příkladu) – a vrátí několik vzorů, které přispívají k rozdílům v těchto dvou sadách:

Snímek obrazovky zobrazující tabulku se třemi řádky Každý řádek zobrazuje rozdíl mezi použitím neobvyklých a standardních hodnot.

Když se podíváte na výsledky dotazu, uvidíte následující rozdíly:

  • Ve všech ostatních dnech v časovém rozsahu dotazů existuje 24 892 147 instancí příjmu dat z prostředku CH1-GEARAMAAKS a žádný příjem dat z tohoto prostředku 15. června. Data z prostředků CH1-GEARAMAAKS představují 73,36 % celkového příjmu dat v jiných dnech v časovém rozsahu dotazů a 0 % celkového příjmu dat 15. června.
  • Ve všech ostatních dnech v časovém rozsahu dotazů existuje 2 168 448 instancí příjmu dat z prostředku NSG-TESTSQLMI519 a 110 544 instancí příjmu dat z tohoto prostředku dne 15. června. Data z NSG-TESTSQLMI519 prostředků představují 6,39 % celkového příjmu dat v jiných dnech v časovém rozsahu dotazů a 25,61 % příjmu dat 15. června.

Všimněte si, že v průměru existuje 108 422 instancí příjmu z prostředku NSG-TESTSQLMI519 během 20 dnů, které tvoří období ostatních dnů (vydělí 2 168 448 o 20). Příjem dat z prostředku NSG-TESTSQLMI519 15. června se proto výrazně neliší od příjmu dat z tohoto prostředku v jiných dnech. Vzhledem k tomu, že od 1. června 15 neexistuje příjem dat z CH1-GEARAMAAKS , příjem dat ze skupiny zabezpečení sítě (NSG-TESTSQLMI519 ) tvoří výrazně větší procento celkového příjmu dat z data anomálií v porovnání s jinými dny.

Sloupec PercentDiffAB zobrazuje absolutní procentuální rozdíl mezi A a B (|PercentA – PercentB|), což je hlavní míra rozdílu mezi těmito dvěma sadami. Modul plug-in ve výchozím nastavení diffpatterns() vrací rozdíl více než 5 % mezi těmito dvěma sadami dat, ale tuto prahovou hodnotu můžete upravit. Pokud například chcete vrátit pouze rozdíly 20 % nebo více mezi těmito dvěma datovými sadami, můžete je nastavit | evaluate diffpatterns(AnomalyDate, "OtherDates", "AnomalyDate", "~", 0.20) v dotazu výše. Dotaz teď vrátí jenom jeden výsledek:

Snímek obrazovky zobrazující tabulku s jedním řádkem, který představuje rozdíl mezi použitím neobvyklých hodnot a využitím směrného plánu Tentokrát dotaz nevrátil rozdíly menší než 20 procent mezi těmito dvěma sadami dat.

Poznámka:

Další informace o diffpatterns() syntaxi a použití najdete v tématu modul plug-in rozdílové vzory.

Další kroky

Přečtěte si další informace: