ディスク空き容量を取得するFluentdのプラグイン作った

# プラグイン作りました
fluentdという様々なデータ収集を統一できるオープンソースのソフトウェアがありますが、プラグインを入れることによって様々で種類のデータを取得したり、加工したりすることができるようになります。

今回は、fluentdを動かしているPCのディスク容量を取得したかったのですが、よさげなプラグインがなかったので作ってみました。RubyGemにも公開済みです。OSSなのでPR, issue歓迎です🙇‍♂

https://github.com/nomunomu0504/fluent-plugin-diskfree

https://rubygems.org/gems/fluent-plugin-diskfree

# 使い方
プラグインをGemでインストールします。

```
$ gem install fluent-plugin-diskfree
```

これでプラグインが利用できるようになるので、fluentdの設定ファイルに追記します。

```conf
<source>
  @type diskfree
  option -k
  refresh_interval 10
  mounted_path /fluentd/etc
  replace_separator true
  trim_percent true
  tag_prefix hostpc.df
</source>
```

それぞれの設定値は以下の通りです。

オプション | 型 | デフォルト値 | 説明
-----|------|-----|------
option | string | -k | dfコマンドに渡すオプション。<br />デフォルトはblock-sizeを1Kとして<br />表示するオプションが設定されています。
refresh_interval | integer | 5 | dfコマンドを実行する間隔。<br />デフォルトは5秒です。
mounted_path | string | / | チェック対象のマウントパスを指定します。<br />デフォルトはルートディレクトリとなっています。
trim_percent | bool | true | dfコマンド結果に現れる`%`を削除します。<br />trueの場合、返却される値の型はint<br />falseの場合は、返却される値の型はstringになります。
replace_separator | bool | true | mounted_pathで指定したパスの`/`を`_`に変換してから返却します。
tag_prefix | string | diskfree | fluentdのタグに接頭語を追加します。

上記のfluent.confの状態で、fluentdを実行すると以下のようなログを取得することができます。

```
hostpc.df._fluentd_etc: {
  "mounted_path":"_fluentd_etc",
  "disksize":250630588,
  "used":147889068,
  "used_percent":59.0,
  "available":102741520,
  "available_percent":40.99,
  "capacity":59
}
```

# 実装解説
fluentd公式サイトに、プラグインの作成方法が掲載されています。基本的にはその方法に従って作成します。
（※ 今回のプラグインを作るときには、fluentd公式の方法を見つけていなくて普通のGemを作る方法で実装してました...🥺）

このプラグインの主要な部分だけ軽く解説しておきます。ソース全体はGithub上に公開されています。

```ruby
# Get df output. splited by line.
result = `#{@execute_command}`.split(/\R/)
# Remove df output header.
result.shift
```

`@execute_command` には実行する df コマンドを指定します。`@execute_command` の定義はこんな感じです。

```ruby
@execute_command = "df -P #{@option} #{@mounted_path} 2> /dev/null"
```

fluent.conf で指定した option や mounted_path を展開して実行する df コマンド作りあげます。上記のconf設定だと、このような df コマンドが実行されます。

```ruby
@execute_command = "df -P -k /fluentd/etc 2> /dev/null"
```

このコマンドを実行すると以下のような結果が返ってきます。それを result の中に格納します。
（※ 表示内容は実行している端末によって異なります。）

```
Filesystem           1024-blocks    Used Available Capacity Mounted on
/dev/mapper/centos-home    250630588 149553004 101077584  60% /fluentd/etc
```

そして `result.shift` を実行することで、df コマンドのヘッダー部分を削除して、必要な情報だけが result の中に残るようにします。

```
# resultの中身
Filesystem           1024-blocks    Used Available Capacity Mounted on
/dev/mapper/centos-home    250630588 149553004 101077584  60% /fluentd/etc
↓
↓ result.shift を実行すると先頭（ヘッダー）が削除されます。
↓
/dev/mapper/centos-home    250630588 149553004 101077584  60% /fluentd/etc
```

ヘッダーを削除した状態で、データを分割して配列化します。
結果を出力するために必要なデータを取得できなかった場合には、エラーログを出力するようにしておきます。

```ruby
data_list = line.split(/\s+/)
log.error("Invalid df output format. #{line}") unless data_list.length == DF_HEADER_COLMUS_LENGTH
```

あとは必要なデータから、出力するデータを生成して終了です。

```ruby
used_percent = ((data_list[2].to_f / data_list[1].to_f) * 100).floor(2)
available_percent = ((data_list[3].to_f / data_list[1].to_f) * 100).floor(2)

disk_info = {
  'mounted_path' => replace_separator?(data_list[5]),
  'disksize' => data_list[1].to_i,
  'used' => data_list[2].to_i,
  'used_percent' => @trim_percent ? used_percent : "#{used_percent}%",
  'available' => data_list[3].to_i,
  'available_percent' => @trim_percent ? available_percent : "#{available_percent}%",
  'capacity' => data_list[4].to_i
}
disk_info
```