Dela via


Tidsserieanalys

Gäller för: ✅Microsoft FabricAzure Data ExplorerAzure MonitorMicrosoft Sentinel

Molntjänster och IoT-enheter genererar telemetridata som kan användas för att få insikter som övervakning av tjänstens hälsa, fysiska produktionsprocesser och användningstrender. Att utföra tidsserieanalys är ett sätt att identifiera avvikelser i mönstret för dessa mått jämfört med deras typiska baslinjemönster.

Kusto Query Language (KQL) innehåller inbyggt stöd för skapande, manipulation och analys av flera tidsserier. I den här artikeln får du lära dig hur KQL används för att skapa och analysera tusentals tidsserier på några sekunder, vilket möjliggör övervakningslösningar och arbetsflöden i nära realtid.

Skapa tidsserier

I det här avsnittet skapar vi en stor uppsättning vanliga tidsserier enkelt och intuitivt med operatorn make-series och fyller i saknade värden efter behov. Det första steget i tidsserieanalys är att partitionera och transformera den ursprungliga telemetritabellen till en uppsättning tidsserier. Tabellen innehåller vanligtvis en tidsstämpelkolumn, kontextuella dimensioner och valfria mått. Dimensionerna används för att partitionera data. Målet är att skapa tusentals tidsserier per partition med jämna mellanrum.

Indatatabellen demo_make_series1 innehåller 600 000 poster med godtycklig webbtjänsttrafik. Använd följande kommando för att prova 10 poster:

demo_make_series1 | take 10 

Den resulterande tabellen innehåller en tidsstämpelkolumn, tre kontextuella dimensionskolumner och inga mått:

Tidsstämpel BrowserVer OsVer Land/region
2016-08-25 09:12:35.4020000 Chrome 51.0 Windows 7 Storbritannien
2016-08-25 09:12:41.1120000 Chrome 52.0 Windows 10
2016-08-25 09:12:46.2300000 Chrome 52.0 Windows 7 Storbritannien
2016-08-25 09:12:46.5100000 Chrome 52.0 Windows 10 Storbritannien
2016-08-25 09:12:46.5570000 Chrome 52.0 Windows 10 Republiken Litauen
2016-08-25 09:12:47.0470000 Chrome 52.0 Windows 8.1 Indien
2016-08-25 09:12:51.3600000 Chrome 52.0 Windows 10 Storbritannien
2016-08-25 09:12:51.6930000 Chrome 52.0 Windows 7 Nederländerna
2016-08-25 09:12:56.4240000 Chrome 52.0 Windows 10 Storbritannien
2016-08-25 09:13:08.7230000 Chrome 52.0 Windows 10 Indien

Eftersom det inte finns några mått kan vi bara skapa en uppsättning tidsserier som representerar själva trafikantalet, partitionerat av operativsystemet med hjälp av följande fråga:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| render timechart 
  • Använd operatorn make-series för att skapa en uppsättning med tre tidsserier, där:
    • num=count(): tidsserier för trafik
    • from min_t to max_t step 1h: tidsserier skapas i 1 timmars intervall i tidsintervallet (äldsta och senaste tidsstämplar för tabellposter)
    • default=0: ange fyllmetod för saknade intervall för att skapa regelbundna tidsserier. Du kan också använda series_fill_const(), series_fill_forward()series_fill_backward()och series_fill_linear() för ändringar
    • by OsVer: partition efter operativsystem
  • Datastrukturen för faktiska tidsserier är en numerisk matris med det aggregerade värdet per tidsintervall. Vi använder render timechart för visualisering.

I tabellen ovan har vi tre partitioner. Vi kan skapa en separat tidsserie: Windows 10 (röd), 7 (blå) och 8.1 (grön) för varje os-version enligt diagrammet:

Tidsseriepartition.

Analysfunktioner för tidsserier

I det här avsnittet utför vi typiska seriebearbetningsfunktioner. När en uppsättning tidsserier har skapats stöder KQL en växande lista över funktioner för att bearbeta och analysera dem. Vi beskriver några representativa funktioner för bearbetning och analys av tidsserier.

Filtrering

Filtrering är en vanlig praxis vid signalbearbetning och användbart för tidsseriebearbetningsuppgifter (till exempel jämna ut en bullrig signal, ändringsidentifiering).

  • Det finns två allmänna filtreringsfunktioner:
    • series_fir(): Använd FIR-filter. Används för enkel beräkning av glidande medelvärde och differentiering av tidsserierna för ändringsidentifiering.
    • series_iir(): Tillämpning av IIR-filter. Används för exponentiell utjämning och kumulativ summa.
  • Extend tidsserien genom att lägga till en ny glidande genomsnittsserie med storlek av 5 intervall (med namnet ma_num) till frågan:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| render timechart

Tidsseriefiltrering.

Regressionsanalys

En segmenterad linjär regressionsanalys kan användas för att uppskatta trenden för tidsserierna.

  • Använd series_fit_line() för att passa den bästa raden till en tidsserie för allmän trendidentifiering.
  • Använd series_fit_2lines() för att identifiera trendändringar, i förhållande till baslinjen, som är användbara i övervakningsscenarier.

Exempel på series_fit_line() och series_fit_2lines() funktioner i en tidsseriefråga:

demo_series2
| extend series_fit_2lines(y), series_fit_line(y)
| render linechart with(xcolumn=x)

Regression av tidsserier.

  • Blå: ursprunglig tidsserie
  • Grön: monterad linje
  • Röd: två monterade linjer

Anmärkning

Funktionen har noggrant identifierat hopppunkten (nivåändring).

Identifiering av säsongsvariationer

Många mått följer säsongsmönster (periodiska). Användartrafiken för molntjänster innehåller vanligtvis dagliga och veckovisa mönster som är högst mitt på arbetsdagen och lägst på natten och under helgen. IoT-sensorer mäter i periodiska intervall. Fysiska mätningar som temperatur, tryck eller luftfuktighet kan också visa säsongsbeteende.

I följande exempel tillämpas säsongsidentifiering på en månads trafik för en webbtjänst (2-timmars intervall):

demo_series3
| render timechart 

Säsongsvariationer i tidsserier.

  • Använd series_periods_detect() för att automatiskt identifiera perioderna i tidsserien, där:
    • num: tidsserierna som ska analyseras
    • 0.: Den minsta tidslängden i dagar (0 innebär inget minimum)
    • 14d/2h: den maximala periodlängden i dagar, vilket är 14 dagar uppdelat i 2-timmars intervall
    • 2: antalet perioder som ska identifieras
  • Använd series_periods_validate() om vi vet att ett mått ska ha specifika distinkta perioder och vi vill kontrollera att de finns.

Anmärkning

Det är en avvikelse om specifika distinkta perioder inte finns

demo_series3
| project (periods, scores) = series_periods_detect(num, 0., 14d/2h, 2) //to detect the periods in the time series
| mv-expand periods, scores
| extend days=2h*todouble(periods)/1d
Perioder Poäng Dagar
84 0.820622786055595 7
12 0.764601405803502 1

Funktionen identifierar dagliga och veckovisa säsongsvariationer. Den dagliga poängen är lägre än veckopoängen eftersom helger skiljer sig från vardagar.

Elementbaserade funktioner

Aritmetiska och logiska åtgärder kan utföras i en tidsserie. Med hjälp av series_subtract() kan vi beräkna en residualtidsserie, dvs. skillnaden mellan det ursprungliga råmåttet och ett utjämnat mått, och leta efter avvikelser i residualsignalen:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| extend residual_num=series_subtract(num, ma_num) //to calculate residual time series
| where OsVer == "Windows 10"   // filter on Win 10 to visualize a cleaner chart 
| render timechart

Tidsserieoperationer.

  • Blå: ursprunglig tidsserie
  • Röd: utjämnade tidsserier
  • Grön: residualtidsserier

Arbetsflöde för tidsserier i stor skala

Exemplet nedan visar hur dessa funktioner kan köras i stor skala på tusentals tidsserier i sekunder för avvikelseidentifiering. Om du vill se några exempeltelemetriposter för en DB-tjänsts mått för läsantal under fyra dagar kör du följande fråga:

demo_many_series1
| take 4 
TIDSSTÄMPEL Loc Op DB DataRead
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 262 0
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 241 0
2016-09-11 21:00:00.0000000 Loc 9 -865998331941149874 262 279862
2016-09-11 21:00:00.0000000 Loc 9 371921734563783410 255 0

Och enkel statistik:

demo_many_series1
| summarize num=count(), min_t=min(TIMESTAMP), max_t=max(TIMESTAMP) 
Num min_t max_t
2177472 2016-09-08 00:00:00.0000000 2016-09-11 23:00:00.0000000

Om du skapar en tidsserie i 1 timmars intervall för läsmåttet (totalt fyra dagar * 24 timmar = 96 poäng) resulterar det i normala mönstervariationer:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h
| render timechart with(ymin=0) 

Tidsserier i stor skala.

Ovanstående beteende är missvisande eftersom den enda normala tidsserien aggregeras från tusentals olika instanser som kan ha onormala mönster. Därför skapar vi en tidsserie per instans. En instans definieras av Loc (location), Op (operation) och DB (specifik dator).

Hur många tidsserier kan vi skapa?

demo_many_series1
| summarize by Loc, Op, DB
| count
Räkna
18339

Nu ska vi skapa en hög av 18339 tidsserier för mätvärdet för läsantal. Vi lägger till by -satsen i instruktionen make-series, tillämpar linjär regression och väljer de två främsta tidsserierna som hade den mest betydande minskande trenden:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc 
| render timechart with(title='Service Traffic Outage for 2 instances (out of 18339)')

Tidsserie topp två.

Visa instanserna:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc
| project Loc, Op, DB, slope 
Loc Op DB backe
Loc 15 37 1151 -102743.910227889
Loc 13 37 1249 -86303.2334644601

På mindre än två minuter analyserades nära 20 000 tidsserier och två onormala tidsserier där läsantalet plötsligt släpptes upptäcktes.

Dessa avancerade funktioner i kombination med snabba prestanda ger en unik och kraftfull lösning för analys av tidsserier.