Datadog でストレージがあと何ヶ月で枯渇するかを予測する

![time_duration_until_the_storage_runs_out_snapshot.png](https://qiita-image-store.s3.amazonaws.com/0/20833/36b455c2-9c35-4b08-b8f5-609d5897dd82.png)

# 概要
Datadog に追加された linear regression functions (線形回帰関数) を利用して、DB などのストレージがあと何ヶ月で枯渇するかを予測するという話。

# 背景
ストレージに対する監視として、使用率が X% を超えたらアラートを出す、というのがオーソドックスなもの。例えば Increments では AWS の推奨閾値である 85 % (出典は関連資料項目を参照) を超えたら Slack に通知が来るようにしている。

しかし、使用率が 85% に達した時、残り 15% をどれくらいの期間で消費するかは実はさまざまなケースがある。緩やかにストレージを消費し、残り 3 ヶ月で消費するケースもあれば、残り 1 週間で消費するケースもあるだろう。残り 1 週間で枯渇するケースの場合、対応が慌ただしくなってしまうかもしれない。

そこで、現在の使用量に対する閾値監視だけでなく、残り何ヶ月でストレージが枯渇するかというデータが欲しくなる。

# ストレージがあと何ヶ月で枯渇するかの予測
ここでは RDS を例にとり、「今のペースで推移した時、あと何ヶ月でストレージが枯渇するか」を可視化してみよう。

利用するのは、`aws.rds.free_storage_space` というメトリクスで、ストレージ残量を表す。

## 週ごとのストレージ消費量の算出
Datadog では、`hour_before()` や `week_before()` といった時間軸をズラしたデータを出す関数がある。これを利用して、まず週ベースの変化量を出そう。

現在の残ストレージ量と 1 週間前の残ストレージ量との差分を取ればいい。

```
week_before(aws.rds.free_storage_space) - aws.rds.free_storage_space
```

## ストレージがあと何週間で枯渇するかの算出
次に、現在の残ストレージ量を週ベースの変化量で割ると、あと何週間で枯渇するかが計算できる。

```
aws.rds.free_storage_space 
/ ( week_before(aws.rds.free_storage_space) - aws.rds.free_storage_space )
```

## ストレージがあと何ヶ月で枯渇するかの算出
「あと X 週間で枯渇する」 という数値を 4 (週間) で割れば「あと X 月で枯渇する」というデータになる

```
aws.rds.free_storage_space 
/ ( week_before(aws.rds.free_storage_space) - aws.rds.free_storage_space ) 
/ 4
```

## 線形回帰関数を使った外れ値への対応
計算に利用しているグラフに外れ値があると、一時的に計算結果がおかしくなり、余計なアラートが飛んでしまう。

例えば、[サービスを止めずにRailsで大きなテーブルにalter tableを実行する - Qiita](http://qiita.com/yuku_t/items/8ff24f99301f7f0dd65b) にあるように、マイグレーション時にテーブルを複製する場合、一時的にストレージを消費する。

Datadog の線形回帰関数を利用すると以下の青線のような外れ値を無視した、紫 (`trend_line()`) や黄色 (`robust_trend()`)の線になる。

![linear_trends](https://qiita-image-store.s3.amazonaws.com/0/20833/fdcff12e-b323-304c-3b96-7fe155bdf1d3.png)

Datadog で選択できる線形回帰の関数には以下の 2 種類ある。

- [Ordinary least squares (最小二乗法)](https://en.wikipedia.org/wiki/Ordinary_least_squares)
- [Huber loss](https://en.wikipedia.org/wiki/Huber_loss)

例に挙げた DB のストレージ消費量は、普段は安定していて、たまに一時的にバーストする傾向があるとしよう。そうするとここでは Ordinary least squares よりも外れ値に強い Huber loss を選択した方がよい。

```
robust_trend(aws.rds.free_storage_space)
/ ( week_before(robust_trend(aws.rds.free_storage_space)) - robust_trend( aws.rds.free_storage_space) )
/ 4
```

これで以下のようなグラフが出せる。

![time_duration_until_the_storage_runs_out_graph.png](https://qiita-image-store.s3.amazonaws.com/0/20833/c0a939bd-058c-7fc2-3d12-29301f2df836.png)

このグラフのスナップショットを表示すれば、「ストレージがあと何ヶ月で枯渇するか予測」の完成だ。

![time_duration_until_the_storage_runs_out_snapshot.png](https://qiita-image-store.s3.amazonaws.com/0/20833/36b455c2-9c35-4b08-b8f5-609d5897dd82.png)

# 補足
RDS のメトリクスの取得頻度が 5 分間隔で、なぜか一時的にストレージ使用率が 100% になってしまう時間帯ができる。

![storage_usage_rate.png](https://qiita-image-store.s3.amazonaws.com/0/20833/dd3e033e-81c3-194c-760f-2a14ea8bfcfd.png)

そこで現在のストレージ量に `hour_before()` を使って、数値がおかしい時間帯を作らないようにしている。

```
robust_trend(hour_before(aws.rds.free_storage_space))
/ ( week_before(robust_trend(aws.rds.free_storage_space)) - robust_trend(hour_before(aws.rds.free_storage_space)) )
/ 4
```

なお、RDS は Enhanced Monitoring を利用すると 1 秒間隔でメトリクスが取得できるようになる。

# まとめ
自分の知る限りは、Datadog は線形回帰グラフを将来に伸ばしてみることはできないので、今回のような形で将来予測を行っている。もしそれできるよ、間違ってるところがある等、フィードバックがあったらどんどんコメントください :pray: 

# 参考資料
## Datadog Official Blog Post
[Visualizing trends with regression lines - Datadog](https://www.datadoghq.com/blog/visualizing-trends-regression-lines/)

## RDS Acceptable Values for Metrics
> **Disk space consumption** – Investigate disk space consumption if space used is consistently at or above 85 percent of the total disk space. See if it is possible to delete data from the instance or archive data to a different system to free up space.

[Best Practices for Amazon RDS - Amazon Relational Database Service](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_BestPractices.html#CHAP_BestPractices.UsingMetrics)