Anomaly Detection (異常値検知)

Anomaly Detection は、アルゴリズムベースの異常検出機能です。過去の挙動、つまり1日のうちの特定の時間帯、あるいは1週間のうちの特定の1日の変動パターンを考慮した際に、普段とは異なる挙動がみられた際に検出することができます。これは、閾値ベースのアラートモニタリングで監視することが困難であったり不可能な、強い傾向のある繰り返しパターンを持ったメトリクスに適しています。

Anomaly Detectionは、例えばWebのトラフィックが平日の午後に異常に低いような場合、それが同日の夜間と同じレベルのトラフィックとして通常はまったくの正常とみなされてしまうような場合であっても、発見することが出来ます。 あるいはまた、堅調にユーザー規模が拡大しているwebサービスへのログイン数を測定しているメトリックについても検討してみてください。数字が毎日増えているため、定数で設定した閾値はすぐに古くなり得ますが、予期せぬ問題が生じてログインシステムに問題が発生している可能性があるような場合は、Anomaly Detectionがすばやく警告することができます。

Anomaly Detectionの利用法

Datadogはanomaliesと呼ぶ新しいクエリ関数を追加しています。メトリクスの時系列データにこの関数を適用すると、”正常と期待される変動幅”を結果として返します。

anomaliesは、将来に期待される変動を予測するために過去の時系列データを使用しますので、データを収集して間もないメトリクスについてanomaliesを適用しても効果は得られないことに注意して下さい。

Anomaly Detectionをダッシュボードで可視化する

下記では、Anomaly Detectionを適用したメトリクスのグラフを表示しています。グレーのバンドは過去の挙動から期待されるメトリクスの正常な変動幅を示しています。青と赤の折れ線は、実際に取得されたメトリクスの値です。また、青い線は正常な変動幅に収まっており、赤い線は変動幅を逸脱していることを示しています。

Anomaly Detectionの利用を開始するには、メトリクスの時系列グラフをダッシュボードに追加することから始めます。下記に示したように、グラフの可視化は “Timeseries” を、グラフ形式を”lines” (折れ線グラフ)として選択します。他の可視化タイプはAnomaly Detectionでは現時点でサポートされておりません。エディター画面は以下のようになります:

次に、メトリクスの各設定ボックスの右手、プラスマークをクリックします。”Modify your query”ボックスで “anomalies” 関数を選択します:

これによりAnomaly Detectionが適用され、即時グラフのプレビュー画面にグレーのバンドが表示されます。この関数は2つのパラメーターを持っています。1つは、どのアルゴリズムを使用するか。もう1つはbounds とラベルされており、グレーのバンドの幅を調整するために使用します。正しく設定されると、エディター画面の表示は以下のようになります:

Anomaly Detectionで異常値をアラートする

ダッシュボード上でAnomaly Detectionを可視化するのに加えて、Anomaly Detectionで判定されたメトリクスの異常値を元にアラートMonitorを作成することができます。 New Monitor ページから新規アラートMonitorの作成を選択し、”Metric”(メトリクスを対象にしたアラート)を選択します。step(1)では他のメトリクスアラートと同様に設定をし、step(2)で”Anomaly Alert”を選択します。

上記のようなエディター画面において、どの程度の強度でAnomaly Detectionを反映するかをいくらかの設定で決定していきます。

  1. ダッシュボードの anomalies 関数で使用した bounds パラメータと同様に、グレーのバンドの幅を指定します。
  2. もし正常な値の幅から異常に高い(低い)場合のみ検出したい場合には、そのように指定します。
  3. 他のアラートと同様に、少ない時間幅にするほど早くアラートを検出できますが、誤検出の増加にもつながります。
  4. Anomaly Detectionのアルゴリズムはここで指定します。

続いて、他のアラートMonitor同様に Step(3)と(4)も設定します。

Anomaly Detectionのアルゴリズム

Anomaly Detectionには、4つの異なるAnomaly Detectionのアルゴリズムを提供しています。

  • Basic: このアルゴリズムは季節性の繰り返しパターンを持たないメトリクスに対して使用します。 Basic アルゴリズムは正常と期待される変動幅を決定するために単純な時間差の移動分位数計算を使用します。僅かなデータ量を使用することで状況の変化に素早く適応しますが、季節性の変動や長期的な傾向は考慮していません。

  • Agile: このアルゴリズムは季節性の変動があるメトリクスにおいて、メトリクス値の推移に素早く追従することが必要な場合に使用します。 Agile アルゴリズムは 季節性ARIMA アルゴリズムをより結果のズレを小さくしたモデルです。現在付近のブレの発生を犠牲にはしつつも、予測には直近の過去の情報を取り込み、値の推移に素早く対応して更新することを可能にしています。

  • Robust: このアルゴリズムは季節性の変動があるメトリクスにおいて、そのメトリクスは比較的安定的に推移をしているが、ゆるやかでも値の推移に変化が生じれば異常とみなしたい場合に使用します。 Robust アルゴリズムは 時系列から季節性変動や特定の傾向を分解 するアルゴリズムです。非常に変動が小さい変動幅を提供します。意図した値の推移(例, コード変更によるメトリクス値の変動)に反応するためにやや時間がかかってしまうという犠牲を払いながらも、一定の予測値を長期的に提供します。

  • Adaptive: このアルゴリズムは季節性の変動があるメトリクスにおいて、メトリクスの挙動における些細な変化に対して agilerobust アルゴリズムが敏感に反応し過ぎると思う場合に使用します。このアルゴリズムはダイナミックで、メトリクス値の変動により敏速に対応した予測値を提供します。その一方で、直近のメトリクスの値の変化に従いすぎる傾向があります。これは、検出のモレが起こりやすいことを意味します。

すべての季節性変動を考慮するアルゴリズムでは、メトリックが正常と見なされる範囲の挙動を計算する際に数ヶ月の過去の時系列データを使用します。膨大な量の過去データを使用することにより、そうしたアルゴリズムでは直近で発生する異常な挙動に重みを置き過ぎることを避けることができます。以下に続く図では、いつどのように4つのアルゴリズムが他と比べて異なる振る舞いをするのかを説明していきます。

In the first figure, basic will successfully identify anomalies that spike out of the normal range of values, but it does not incorporate the repeating, seasonal pattern into its predicted range of values. By contrast, robust, agile, and adaptive all recognize the seasonal pattern and can detect more nuanced anomalies (e.g., if the metric was to flatline near its minimum value).

次の図では、メトリクスの推移が急に変化した場合を示しています。 Agile and adaptive adjust more quickly to the level shift than does robust. Also, the width of robust’s bounds increases to reflect greater uncertaintly after the level shift; the width of agile and adaptive bounds remains unchanged. Basic is clearly a poor fit for this scenario, where the metric exhibits a strong weekly seasonal pattern.

さらに次の図では、メトリクスが1時間ほど異常な値に推移していた場合に各アルゴリズムがどのように反応するかを示しています。 Robust completely ignores this anomaly. All the other algorithms start to behave as if the anomaly is the new normal. Agile and adaptive even identify the metric’s return to its original level as an anomaly.

また、各アルゴリズムでは(Y軸)スケールの違いでも振る舞いが異なります。 BasicRobust は スケールの違いで差が生じにくい一方で、 AgileAdaptive は スケールの違いで振る舞いが変わります。 In the graphs on the left-hand side we see both Agile and Robust mark the level-shift as being anomalous. On the right-hand side we add 1000 to the same metric, and Agile no longer calls out the level-shift as being anomalous whereas robust continues do so.

最後に、それぞれのアルゴリズムが新しいメトリクスの値をどのように扱うかを見てみましょう。 Robust and agile won’t show any bounds during the first few weeks. Basic and adaptive will start showing bounds shortly after the metric first appears. Adaptive will leverage the metric’s daily seasonal patterns in its predictions, while basic simply reflects the range of recent values.

よくあるご質問(FAQs)

すべてのメトリクスにAnomaly Detectionを利用するべきですか?

いいえ。Anomaly Detectionは予想可能なパターンを持つメトリクスの監視や可視化を支援する目的でデザインされています。例えば、my_site.page_views のようなユーザーによるwebトラフィックの場合、1日のうちの特定の時間帯、あるいは1週間のうちの特定の1日を想定すると、通常はある程度予測可能な変動をしていると考えられます。もしメトリクスがそういった繰り返しの/予測可能なパターンを持っていないのであれば、Anomaly Detectionを用いずに通常のグラフによる可視化や閾値によるアラートの設定が有効だと考えられます。

また、Anomaly Detectionは効果的な予測値のために過去の時系列データを必要としますので、もしメトリクスの収集を始めてから数時間あるいは数日である場合、Anomaly Detectionは恐らく有効には機能しないでしょう。

Multi Alert を設定しているときには注意が必要です。service.requests_served{*} のようなメトリックはAnomaly Detection を適用する良い候補に思われますが、一方で、そのメトリックをホストごとにスライスした service.requests_served{*} by {host} は良い候補とはならないでしょう。もしそれらのホストがロードバランサー配下にあるのであれば、むしろOutlier Detection が異常なホストの検知に適していると思われます。 サービスがスケールしていく場合では、追加されていく新しいホストは Anomaly Detection に必要な過去の時系列データが蓄積するまで全く監視されず、それどころか、それらのホストによるリクエストの数が不安定になることでアラートが不必要にトリガされる可能性もあります。

なぜメトリクスのグループに対してAnomaly Detectionを利用できないのですか?

1つのグラフ表示上で多数の独立した時系列データを可視化しようとすると、 spaghettification 問題が生じ得ます。そしてこの問題は、Anomaly Detection をグラフに追加しようとするとさらに悪化してしまいます。

1つのグラフ表示上に多数の時系列データを表示させることはもちろん可能ですが、Anomaly Detectionのグレーのバンドの予測値はマウスオーバーした際のみに見えるようになっています。

異常値が検出された場合、これから予測される異常値は影響を受けますか?

Basic を除く全てのアルゴリズムは膨大な過去の時系列データを使用しているため、ほとんどの異常値に対して堅牢です。最初のグラフでは、メトリックの値が0に下がった後でもグレーのバンドは400K付近に留まっていることがわかります。そして、その後その日中も同様にグレーのバンドが推移していることに注目して下さい。

2つ目も同じメトリックのグラフですがさらに1日後のものです。グレーのバンドを計算するうえで前日のデータも処理されているものの、当時発生した異常値に対して影響を受けていないことが分かります。

アラートの閾値と判定の時間枠はどのように設定すれば良いでしょうか?

Smaller window sizes will lead to faster alerts, however, with very small windows (<= 10 minutes), metrics often appear noisy, making it difficult to visualize the difference between anomalies and noise.

Note that setting the window size to X minutes doesn’t require an anomaly to last X minutes before an alert is triggered. You can tune the threshold to control how long an anomaly must last to trigger an alert. For example, with the window size set to 30 minutes, you can get alerted when an anomaly lasts for just five minutes by setting the threshold to 530 = 17%. That said, we have found that anomaly alerts are most reliable when the window size is between 15 minutes and an hour and the threshold is on the higher side (> 40%).

anomalies 関数が予測値のグレーのバンドをダッシュボードに描画しないのですが、なぜでしょうか? / Anomaly アラートを設定したのですが、なぜ “No Data” となってしまうのでしょうか? / このアルゴリズムでは、どの程度のメトリクスの履歴が必要ですか?

Basic を除く全てのアルゴリズムでは予測を開始するうえで過去の時系列データを必要とします。もし、設定したメトリックがDatadogに収集され始めて間もない場合は、AgileRobust アルゴリズムは少なくとも2週間分のメトリクス履歴を得るまでは予測値の算出を実行しません。Adaptive アルゴリズムについては、少なくとも2時間分にあたる履歴が得られた時点で予測値の算出を始めます。

なぜグラフを拡大(ズームイン)した際にAnomaly Detection が消えてしまうのでしょうか?

異なるズームレベルでは、同じクエリであってもかなり異なる特徴をもった時系列データを得ることもあり得ます。比較的長い時間幅でグラフ表示する場合、各データポイントでは多数のより小さな粒度のデータポイントが集計されています。このため、そうして集計された各データポイントでは、より小さな粒度のデータポイントに存在していたノイズが隠れてしまいます。例えば、1週間の時間幅のグラフ表示では、しばしば10分の時間幅のグラフ表示よりも滑らかに(ノイズが少なく)見えるでしょう。

Anomaly Detectionアルゴリズムによって描画されるグレーのバンドの幅は、ある程度、プロットされる時系列データのノイズの加減に基づいています。普段のノイズがほぼバンドの内側に収まり異常値として検出されないくらい十分に、バンドは広く表示されるはずです。残念ながら、特に短い時間幅でグラフ表示するような場合は、普段のノイズを収めるほど十分な幅のバンドであれば、いくらかの異常値もまたその幅の内側に隠れてしまうでしょう。

ここで具体的な例を見てみましょう。app.requests メトリクスは非常にノイジーですが、平均値としては8で一定です。ある日、9:00頃に始まった10分間の異常な時間帯があり、その10分間の平均値は10でした。下記のグラフはこの時系列データを1日の時間幅で表したものです。それぞれのデータポイントは5分間を集計したものになっています。

この例ではグレーのバンドは適切といえます。この時系列データのノイズを捉えるのに十分な広さの幅です。しかし、9:00頃に始まったノイズを明確に捉えるにはやや狭い幅ともいえます。では、次のグラフはどうでしょうか。ズームインしたグラフは異常な10分間を含む30分の時間幅で表されています。それぞれのデータポイントは10秒間を集計したものになっています。

繰り返しになりますが、この例でもグレーのバンドは適切のように見えます。なぜなら、異常ではない8:50から9:00と9:10から9:20のデータはバンドの内側に収まっているからです。バンドは狭くさえすれば、いかなる正常なデータも異常値として切り出せます。このバンドが前のグラフよりも8倍近く広くなっていることにお気づきでしょうか? この9:00から9:10の異常な10分間では、他の部分の時系列データとは少し違うように見えますが、バンドの外側に飛び抜けるほどのものではありません。

ズームインするとAnomaly Detectionによる異常値の検出が消えるような場合、一般的には、異常値ではないことを意味するわけではありません。ズームインした時間幅での個々のデータポイントが異常値として検出されない一方で、これは、普段とはわずかに異なる多くのデータポイントが同時に発生したことが異常だと意味しているのです。

Is it possible to capture anomalies that occur within the bounds?

If the reason anomalies are occurring within the bounds is that the volatility of a metric leads to wide bounds that mask true anomalies (as described in the FAQ above), you may be able apply functions to the series to reduce its volatility, leading to narrower bounds and better anomaly detection.

For example, many important metrics (e.g., successful.logins, checkouts.completed, etc.) represent the success of some user-driven action. It can be useful to monitor for anomalous drops in one of those metrics, as this may be an indication that something is preventing successful completion of these events and that the user experience is suffering.

It’s common that these metrics have points that are at or near zero, especially when viewing the metric over a short window of time. Unfortunately, this results in the bounds of the anomaly detection forecast include zero, making it impossible to detect anomalous drops in the metric. An example is shown below.

How can we work around this problem? One approach is to add a rollup() to force the use of a larger interval. rollup() takes as an argument the number of seconds that should be aggregated into a single point on the graph. For example, applying rollup(120) will lead to a series with one point every two minutes. With larger intervals, zeros become rare and can correctly be categorized as anomalies. Here’s the same series as above but with a 2-minute rollup applied.

Another option is to apply the ewma() function to take a moving average. Like with rollups, this function will smooth away intermittent zeros so that drops in the metric can correctly be identified as anomalies.