📈

作業時間を Disk I/O を元に Grafana + InfluxDB で可視化する

2023/10/01に公開

背景

みなさんは GitHub の Contribution Graph (所謂「草」) を見ていますか?

私はよく、その頃何をしていたのかの目安にしたり、作業の記録として確認したりします。しかし、このグラフに表示されるのはデフォルトブランチへのコミットのみで、長期間マージされない貢献などは表示してくれず、また、本記事のようなインフラ関連のツールのセットアップなどはそもそも貢献としてカウントされません。

そのため、継続日数などを目標にすることが難しくなっていると感じています。

作るもの

そこで今回は、 InfluxDB + Telegraf で収集した Disk I/O のデータを Grafana を使って表示し、作業時間を測ってみよう!という記事です。幸いにも私はほとんどの開発を専用の VPS を利用して行っているので、何も考えずに VPS 上でシステム全体の Disk I/O を記録します。

セットアップ

とりあえず Grafana, InfluxDB, Telegraf をそれぞれインストールし、有効化・起動します。
環境は Vultr 上の Arch Linux 4GB RAM / 2 vCPUs です。 (執筆時 2023.10.01)

sudo pacman -S grafana influxdb

sudo systemctl enalbe grafana
sudo systemctl start grafana

sudo systemctl enable influxdb
sudo systemctl start influxdb

yay -S telegraf-bin

sudo systemctl enable telegraf
sudo systemctl start telegraf

これで、デフォルトは Grafana は :3000, InfluxDB は :8086 で立ち上がるはずです。 http://localhost:8086 にアクセスして、 InfluxDB の設定をしましょう。

好きなようにユーザを作成します。この時、 Initial Organization Name と Initial Bucket Name をメモしておいてください。

うまく設定できれば、発行されたトークンが表示されるので、これもメモしておきます。

その後、 Telegraf の設定ファイル /etc/telegraf/telegraf.conf を以下のように変更し、 InfluxDB へのデータの流し込みを設定します。先程メモしておいたトークンや Organization Name / Bucket Name を変更し、必要があれば URL も自身の InfluxDB のものに合わせて修正してください。

# # Configuration for sending metrics to InfluxDB 2.0
- # [[outputs.influxdb_v2]]
+ [[outputs.influxdb_v2]]
#   ## The URLs of the InfluxDB cluster nodes.
#   ##
#   ## Multiple URLs can be specified for a single cluster, only ONE of the
#   ## urls will be written to each interval.
#   ##   ex: urls = ["https://us-west-2-1.aws.cloud2.influxdata.com"]
-   urls = []
+   urls = ["http://127.0.0.1:8086"]
#
#   ## Token for authentication.
-  token = ""
+  token = "YOUR_TOKEN"
#
#   ## Organization is the name of the organization you wish to write to.
-   organization = ""
+   organization = "YOUR_ORGANIZATION_NAME"
#
#   ## Destination bucket to write into.
-   bucket = ""
+   bucket = "YOUR_BUCKET_NAME"
#
sudo systemctl restart telegraf

データの表示

Telegraf を再起動したら、 InfluxDB を Grafana に繋ぎこみます。 Grafana のデータソースとして、 InfluxDB を設定し、 Flux という言語を用いて以下のようなクエリを記述してみます。

from(bucket: "YOUR_BUCKET_NAME")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r._measurement == "diskio" and r._field == "write_bytes")
  |> aggregateWindow(every: 10m, fn: sum)
  |> yield(name: "write_bytes")

これを Grafana で Time series として表示するとこのようになりました。
何かしらの Disk I/O データは取得できていそうですが、単調に増加していくつかの点で急激に下る、という書き込み量としてはおかしいものになってしまっています。

クエリの修正

調べてみると、先程のクエリで取得できるのは累積された書き込み量だったようです。
時間ごとの差分を見れば良さそうなので、 difference() を使ってクエリを修正してみます。

from(bucket: "YOUR_BUCKET_NAME")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r._measurement == "diskio" and r._field == "write_bytes")
+   |> difference(nonNegative: true, initialZero: true)
  |> aggregateWindow(every: 10m, fn: sum)

かなりそれっぽくなりましたね。作業をしていた 13 時付近と、この記事を書いている 6 時付近が高くなっていることが明確にわかります。

一日あたりの閾値を超えた回数を表示

最後に、1日あたりの閾値を超えた回数をカウントするようなパネルも追加してみました。

from(bucket: "YOUR_BUCKET_NAME")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r._measurement == "diskio" and r._field == "write_bytes")
  |> difference(nonNegative: true, initialZero: true)
  |> map(fn: (r) => ({ r with _value: if r._value > 30000000 then 1 else 0 }))
  |> aggregateWindow(every: 1d, fn: sum)

問題ないように見えますが、全くの初心者で判断できないのでしばらく使ってみて、それっぽいデータになっていなかったらまた修正してみます。

また、先程の書き込み量のグラフに対して、今 SSH が何本貼られているかなどのデータを利用してアノテーションをするとさらに便利になるかなと思います。

まとめ

思ったよりもサクッとやりたかったことが達成できました。これで自分が作業している時間が少しは正確に測れるのではないかなと思います。本当はもっと GitHub の Contribution Graph に見た目を寄せたかったんですが、また時間のあるときに調べてみようと思います。

最後までお読みいただきありがとうございました!

Discussion