時系列分析

クラウド サービスと IoT デバイスは、サービスの正常性の監視、物理的な運用プロセス、使用状況の傾向などの分析情報を得るために使用できるテレメトリ データを生成します。 時系列分析の実行は、一般的なベースライン パターンと比較して、これらのメトリックのパターンの偏差を特定する 1 つの方法です。

Kusto 照会言語 (KQL) には、複数の時系列の作成、操作、分析のためのネイティブ サポートが含まれています。 この記事では、KQL を使用して数千の時系列を秒単位で作成および分析し、ほぼリアルタイムの監視ソリューションとワークフローを可能にする方法について説明します。

時系列の作成

このセクションでは、make-series 演算子と、必要に応じて欠損値を使用して、一定間隔の時系列の大きいセットを簡単かつ直感的に作成します。 時系列分析の最初の手順では、パーティション分割し、元のテレメトリ テーブルを時系列のセットに変換します。 テーブルには、通常、タイムスタンプ列、コンテキスト ディメンション、および省略可能なメトリックが含まれています。 ディメンションは、データをパーティション分割するために使用されます。 目標は、一定の時間間隔でパーティションあたり何千もの時系列を作成することです。

入力テーブル demo_make_series1 には、任意の Web サービス トラフィックの 600 件のレコードが含まれています。 次のコマンドを使用して、10 個のレコードをサンプリングします。

demo_make_series1 | take 10 

結果のテーブルには、1 つのタイムスタンプ列、3 つのコンテキスト ディメンション列が含まれ、メトリックは含まれていません。

TimeStamp BrowserVer OsVer 国/地域
2016-08-25 09:12:35.4020000 Chrome 51.0 Windows 7 イギリス
2016-08-25 09:12:41.1120000 Chrome 52.0 Windows 10
2016-08-25 09:12:46.2300000 Chrome 52.0 Windows 7 イギリス
2016-08-25 09:12:46.5100000 Chrome 52.0 Windows 10 イギリス
2016-08-25 09:12:46.5570000 Chrome 52.0 Windows 10 リトアニア共和国
2016-08-25 09:12:47.0470000 Chrome 52.0 Windows 8.1 インド
2016-08-25 09:12:51.3600000 Chrome 52.0 Windows 10 イギリス
2016-08-25 09:12:51.6930000 Chrome 52.0 Windows 7 オランダ
2016-08-25 09:12:56.4240000 Chrome 52.0 Windows 10 イギリス
2016-08-25 09:13:08.7230000 Chrome 52.0 Windows 10 インド

メトリックがないため、構築できるのは、次のクエリを使用して OS ごとにパーティション分割された、トラフィック数そのものを表す時系列のセットのみです。

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 
  • make-series 演算子を使用して、次の 3 つの時系列のセットを作成します。
    • num=count(): トラフィックの時系列
    • from min_t to max_t step 1h: 時系列は時間範囲 (テーブル レコードの最も古いタイムスタンプと最も新しいタイムスタンプ) 内の 1 時間のビンに作成されます
    • default=0: 一定間隔の時系列を作成するために、欠測ビンを埋める方法を指定します。 または、変化に対して series_fill_const()series_fill_forward()series_fill_backward()、および series_fill_linear() を使用します
    • by OsVer: OS ごとのパーティション分割
  • 実際の時系列データの構造は、各時間ビンごとに集計された値の数値配列です。 視覚化には render timechart を使用します。

上の表には、3 つのパーティションがあります。 次のグラフに示すように、OS バージョンごとに Windows 10 (赤)、7 (青)、および 8.1 (緑) の個別の時系列を作成できます。

時系列のパーティション。

時系列の分析関数

このセクションでは、一般的な時系列処理関数を実行します。 時系列のセットが作成されると、KQL はそれらを処理および分析するための関数の増加する一覧をサポートします。 時系列を処理および分析するための代表的な関数をいくつか説明します。

フィルター処理

フィルター処理は信号処理の一般的な方法であり、時系列処理タスク (ノイズの多い信号の円滑化や変化検出など) で有効です。

  • 次の 2 つの一般的なフィルター処理関数があります。
    • series_fir(): FIR フィルターを適用します。 変化検出のための時系列の移動平均と微分の単純な計算に使用します。
    • series_iir(): IIR フィルターを適用します。 指数平滑法と累積合計に使用します。
  • サイズ 5 のビンの新しい移動平均系列 (名前は ma_num) をクエリに追加することで、時系列セットに Extend を実行します。
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

時系列のフィルター処理。

回帰分析

Azure Data Explorer では、時系列の傾向を推定するためのセグメント化線形回帰分析がサポートされています。

  • series_fit_line() を使用して、一般的な傾向の検出のために最適な直線を時系列に合わせます。
  • series_fit_2lines() を使用して、ベースラインに対して相対的な傾向変化を検出します。監視シナリオで役立ちます。

時系列のクエリでの series_fit_line() 関数と series_fit_2lines() 関数の例を、次に示します。

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

時系列回帰。

  • 青: 元の時系列
  • 緑: 適合する直線
  • 赤: 2 つの適合する直線

注意

この関数により、ジャンプ (レベルの変化) ポイントが正確に検出されました。

季節性の検出

多くのメトリックは、季節的な (定期的な) パターンに従います。 クラウド サービスのユーザー トラフィックには、営業日の昼頃が最も多く夜間と週末が最も少ないという、日単位と週単位のパターンが含まれています。 IoT センサーは定期的な間隔で測定を行います。 温度、気圧、湿度などの物理学的測定が季節的な動作を示すもこともあります。

次の例では、Web サービス (2 時間のビン) の 1 か月間のトラフィックに季節性の検出を適用します。

demo_series3
| render timechart 

時系列の季節性。

  • series_periods_detect() を使用して、時系列の期間を自動的に検出します。
  • メトリックに個別の特定の期間が含まれていることがわかっていて、それらが存在することを確認したい場合は、series_periods_validate() を使用します。

注意

これは、個別の特定の期間が存在しない場合は異常です

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
periods スコア days
84 0.820622786055595 7
12 0.764601405803502 1

この関数で、日単位と週単位の季節性が検出されます。 週末は平日と異なるため、日単位のスコアは週単位のスコアより少なくなります。

要素ごとの関数

時系列では算術演算と論理演算を実行できます。 series_subtract() を使用すると、残差時系列、つまり、元の未加工のメトリックと平滑化されたメトリックの間の差を計算して、残差信号の異常を調べることができます。

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 in 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

時系列の演算。

  • 青: 元の時系列
  • 赤: 平滑化された時系列
  • 緑: 残差系列

大規模な時系列のワークフロー

次の例は、異常検出のために、何千もの秒単位の時系列でこれらの関数を大規模に実行する方法を示しています。 4 日間にわたる DB サービスの読み取り回数のメトリックの、いくつかのサンプルのテレメトリ レコードを確認するには、次のクエリを実行します。

demo_many_series1
| take 4 
timestamp Loc 操作 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

シンプルな統計は次のとおりです。

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

読み取りメトリックの 1 時間のビンで時系列を構築すると (4 日 * 24 時間の合計 = 96 ポイント)、結果として正常なパターンの変動が発生します。

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) 

大規模な時系列。

上記の動作は誤解を招く恐れがあります。1 つの正常な時系列が、異常パターンが含まれる可能性のある何千もの別のインスタンスから集計されるためです。 そのため、インスタンスごとの時系列を作成します。 インスタンスは、Loc (location)、Op (operation)、DB (特定のマシン) によって定義されます。

時系列はいくつ作成できるでしょうか。

demo_many_series1
| summarize by Loc, Op, DB
| count
Count
18339

ここで、読み取り回数のメトリックの 18339 の時系列のセットを作成します。 make-series ステートメントに by 句を追加し、線形回帰を適用して、最も重要な減少傾向があった上位 2 つの時系列を選択します。

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)')

時系列の上位 2 つ。

インスタンスを表示します。

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 操作 DB 傾き
Loc 15 37 1151 -102743.910227889
Loc 13 37 1249 -86303.2334644601

2 分未満で、20,000 件近くの時系列が分析され、読み取りカウントが突然削除された 2 つの異常な時系列が検出されました。

これらの高度な機能と高速パフォーマンスを組み合わせることで、時系列分析のためのユニークで強力なソリューションが提供されます。