fluentdのoutputプラグインの作成

fluentdのoutputプラグインを作成する道のりです。

Ruby, gemはすでに入っているものとします。以下の手順で進めます。

1. fluentdをインストール
2. サンプルプラグイン作成
3. fluentd設定ファイルを修正
4. サンプルプラグインでfluentdを起動
5. サンプルプラグインを修正する形で開発
6. gem作成

# fluentdをインストール

```
$ gem install -N fluentd
$ fluentd --version
fluentd 1.7.4
```

シンプルな設定ファイルとして以下のファイルを作成します。

```sample.conf
<source>
  @type tail
  path input.txt
  pos_file input.pos
  tag test
  <parse>
    @type none
  </parse>
</source>
<match test>
  @type stdout
</match>
```

fluentdを起動してみます。

```
$ touch input.txt
$ fluentd -c sample.conf
```

別のターミナルで以下のようにすると、

```
echo hello >> input.txt
```

さきほどのfluentdから以下のように出力され、正常に動いていることを確認できます。

```
2019-10-28 12:57:50.817045876 +0900 test: {"message":"hello"}
```

# サンプルプラグイン作成

`fluent-plugin-generate`というコマンドでプラグインのひな型を生成できます。このコマンドはfluentdをインストールしたときに同時にインストールされています。

```
$ fluent-plugin-generate output sample
License: Apache-2.0
        create Gemfile
        create README.md
        create Rakefile
        create fluent-plugin-sample.gemspec
        create lib/fluent/plugin/out_sample.rb
        create test/helper.rb
        create test/plugin/test_out_sample.rb
```
fluent-plugin-generateに渡しているパラメータの`output`はプラグインの種類、2つ目のパラメータの`sample`はプラグインの名前です。名前はここではサンプルとしていますが、初めから作りたいプラグインの内容に応じた名前をここで付けておいたほうが早いです。`fluent-plugin-`で始まる名前が慣例の模様。

ディレクトリが生成され、その中で`git init`まで済ました状態になっています。とりあえずそのままコミットするのがいいかもしれません。

```
$ cd fluent-plugin-sample
$ git add -A
$ git commit -m 'first commit'
$ cd ..
```

作成されたディレクトリの中の `lib/fluent/plugin/out_sample.rb` というファイルがプラグインの本体になります。最低限動かすためのひな型として以下のようにします。なにも定義しないとfluentdが起動しないです。（`BUG: output plugin must implement some methods. see developer documents.` というエラーメッセージになります）

```fluent-plugin-sample/lib/fluent/plugin/out_sample.rb
module Fluent
  module Plugin
    class SampleOutput < Fluent::Plugin::Output
      Fluent::Plugin.register_output("sample", self)

      def format(tag, time, record)
        [tag, time, record].to_msgpack
      end

      def formatted_to_msgpack_binary?
        true
      end

      def write(chunk)
        chunk.msgpack_each do |tag, time, data|
          p tag
          p time
          p data
        end
      end

    end
  end
end
```

# fluentd設定ファイルを修正

さきほど作った`sample.conf`の後半を以下のようにして、sampleプラグインが動くように変更します。

```
<match test>
  @type sample
  <buffer>
    chunk_limit_records 1
  </buffer>
</match>
```

`@type`のところが使用するoutputプラグインの名前です。

`chunk_limit_records`の設定は、デバッグ目的でバッファリングの容量を1レコードのみにして実質バッファリングせずに入力されたらすぐに出力することを指示するものです。

Config: Buffer Section - Fluentd
https://docs.fluentd.org/configuration/buffer-section#buffering-parameters

# サンプルプラグインでfluentdを起動

fluent-plugin-generateで作成したサンプルプラグインを含めてfluentdを起動し、別のターミナルで `echo hello >> input.txt` とするとサンプルプラグインが動いていることを確認できます。

```
$ fluentd -c sample.conf -p fluent-plugin-sample/lib/fluent/plugin
...
"test"
1572238328
{"message"=>"hello"}
```

# サンプルプラグインを修正する形で開発

`fluent-plugin-sample/lib/fluent/plugin/out_sample.rb`を好きなように開発します。
依存するgemがあれば、のちにプラグインをgem化するのに備えて`fluent-plugin-sample.gemspec`に以下のように書いておきます。

```
spec.add_runtime_dependency "foolibrary"
```

# gem作成

`fluent-plugin-sample/fluent-plugin-sample.gemspec`を編集します。少なくとも`TODO`と書かれている3行を以下のように適当に変更します。

```ruby
  spec.summary       = %q{sampe fluent plugin.}
  spec.description   = %q{sampe fluent plugin.}
  spec.homepage      = "http://www.example.com/"
```

以下のコマンドを実行するとパッケージが生成されます。

```
$ cd fluent-plugin-sample
$ rake build
```

`fluent-plugin-sample`の中の`pkg/fluent-plugin-sample-0.1.0.gem`にファイルが生成されます。

あとはRubyGemsに登録するなどすれば完了です。

# 参考

- [fluentdのpluginを作成する （fluent-plugin-generateコマンド利用） - Qiita](https://qiita.com/tanan/items/625329234dc2b36a1c58)
- [fluentdのプラグインをgemでインストール - Qiita](https://qiita.com/suzuki-navi/items/3014e9cb60c85b29fdff)