本日も乙

ただの自己満足な備忘録。

Fluentdプラグインを作ってRubyGems.orgに公開するまでの手順をまとめた

Fluentdプラグイン作りました

ohsawa0515/fluent-plugin-grepcount-filter

どういうプラグインかというと、正規表現でマッチしたログが閾値以上になった場合のみ通すというものでfluent-plugin-grepcounterfluent-plugin-datacounterを合わせたようなプラグインです。作る際にこの2つのプラグインを大変参考にさせていただきました。ありがとうございます。

なぜ作ったのか

「○○というエラーが一定時間内に一定回数以上流れてきたログのみを収集したい」という要望があったためです。当初はfluent-plugin-grepcounterだけを使えばできるじゃん!と思ったのですが、フィルタしたい条件が複数(AND)になった場合にログの中身(message)を出力しないことがわかり採用できませんでした。PRを送ろうかと考えましたが、ユースケースが限定的だなと思ったのと、ログをほとんど加工しないようにしたかったため新規で作ることにしました。

本題

本記事ではFluentdプラグインを作ってからRubyGems.orgに公開するまでの手順をメモしたので公開します。

実行環境

  • CentOS 7.2
  • td-agent v2.2.0 (Fluentd v0.12.7)

準備

Fluentdの実行環境を用意する

$ sudo yum -y install gcc git vim
$ git config --global user.name "Shuichi Ohsawa"
$ git config --global user.email "ohsawa0515@gmail.com"

td-agentをインストールします。ラベル機能を使い勝ったので、Fluentd v0.12以上が入っているバージョンにします。 ここから好きなバージョンのRPMを選びます。

$ sudo rpm -ivh http://packages.treasuredata.com.s3.amazonaws.com/2/redhat/7/x86_64/td-agent-2.2.0-0.x86_64.rpm
http://packages.treasuredata.com.s3.amazonaws.com/2/redhat/7/x86_64/td-agent-2.2.0-0.x86_64.rpm を取得中
警告: /var/tmp/rpm-tmp.TR2Ykq: ヘッダー V4 DSA/SHA1 Signature、鍵 ID a12e206f: NOKEY
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:td-agent-2.2.0-0                 ################################# [100%]
adding 'td-agent' group...
adding 'td-agent' user...
Installing default conffile...
prelink detected. Installing /etc/prelink.conf.d/td-agent-ruby.conf ...
Configure td-agent to start, when booting up the OS...

gem listでv0.12以上のFluentdがインストールされていればOKです。

$ export PATH=$PATH:/opt/td-agent/embedded/bin
$ gem list | grep fluentd
fluentd (0.12.7)
fluentd-ui (0.3.18)

td-agentを起動します。

$ sudo systemctl enable td-agent
td-agent.service is not a native service, redirecting to /sbin/chkconfig.
Executing /sbin/chkconfig td-agent on
$ sudo systemctl start td-agent
$ sudo systemctl status td-agent
● td-agent.service - LSB: td-agent's init script
   Loaded: loaded (/etc/rc.d/init.d/td-agent)
   Active: active (running) since 木 2016-05-26 10:44:31 UTC; 15s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 13578 ExecStart=/etc/rc.d/init.d/td-agent start (code=exited, status=0/SUCCESS)
 Main PID: 13588 (ruby)
   CGroup: /system.slice/td-agent.service
           ├─13588 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --group td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --daemon /var/run/td-agent/td-agent.pid
           └─13591 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --group td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --daemon /var/run/td-agent/td-agent.pid

 5月 26 10:44:30 centos7 systemd[1]: Starting LSB: td-agent's init script...
 5月 26 10:44:30 centos7 runuser[13581]: pam_unix(runuser:session): session opened for user td-agent by (uid=0)
 5月 26 10:44:31 centos7 runuser[13581]: pam_unix(runuser:session): session closed for user td-agent
 5月 26 10:44:31 centos7 td-agent[13578]: Starting td-agent: [  OK  ]
 5月 26 10:44:31 centos7 systemd[1]: Started LSB: td-agent's init script.

ディレクトリ、ファイルの準備

Bundlerをインストールします。
gemコマンドはtd-agentをインストールすると同梱されていますが、すでにgemがインストールされていればそれを使っても良いです。

$ export PATH=$PATH:/opt/td-agent/embedded/bin
$ gem install bundler

Fluentdプラグインの雛形を作成します。

$ bundle gem fluent-plugin-grepcount-filter
Creating gem 'fluent-plugin-grepcount-filter'...
Do you want to include a code of conduct in gems you generate?
Codes of conduct can increase contributions to your project by contributors who prefer collaborative, safe spaces. You can read more about the code of conduct at contributor-covenant.org. Having a code of conduct means agreeing to the responsibility of enforcing it, so be sure that you are prepared to do that. For suggestions about how to enforce codes of conduct, see bit.ly/coc-enforcement. y/(n): y
Code of conduct enabled in config
Do you want to license your code permissively under the MIT license?
This means that any other developer or company will be legally allowed to use your code for free as long as they admit you created it. You can read more about the MIT license at choosealicense.com/licenses/mit. y/(n): y
MIT License enabled in config
Do you want to generate tests with your gem?
Type 'rspec' or 'minitest' to generate those test files now and in the future. rspec/minitest/(none): y
      create  fluent-plugin-grepcount-filter/Gemfile
      create  fluent-plugin-grepcount-filter/.gitignore
      create  fluent-plugin-grepcount-filter/lib/fluent/plugin/grepcount_filter.rb
      create  fluent-plugin-grepcount-filter/lib/fluent/plugin/filter_counter/version.rb
      create  fluent-plugin-grepcount-filter/fluent-plugin-grepcount-filter.gemspec
      create  fluent-plugin-grepcount-filter/Rakefile
      create  fluent-plugin-grepcount-filter/README.md
      create  fluent-plugin-grepcount-filter/bin/console
      create  fluent-plugin-grepcount-filter/bin/setup
      create  fluent-plugin-grepcount-filter/CODE_OF_CONDUCT.md
      create  fluent-plugin-grepcount-filter/LICENSE.txt
Initializing git repo in /repository/fluent-plugin-filter_count

ディレクトリやファイルなどを作成します。

$ cd fluent-plugin-grepcount-filter
$ rm -rf bin lib/fluent/plugin/grepcount_filter
$ mkdir -p test/plugin
$ touch test/plugin/.keep

実装&動作確認

プラグインの実装ができたら動作確認します。

test.confというファイルを用意してダミー用のデータを流してフィルタされた結果が出力されるかを検証します。
ダミー用データはin_dummpyプラグインを使います。

# /etc/td-agent/conf.d/test.conf

<source>
  type dummy
  tag raw.test
  dummy {"log_level":"WARN", "message": "foo bar baz"}
  rate 4
</source>

<match raw.test>
  type grepcount_filter
  regexp1 log_level WARN
  regexp2 message foo
  count_interval 10s
  threshold 30
  output_setting true
  @label @output
</match>

<label @output>
  <match **>
    type stdout
  </match>
</label>
$ sudo td-agent -c /etc/td-agent/td-agent.conf -p lib/fluent/plugin/ -v

以下のようなデータがログに出力されればOKです。

2016-05-26 11:59:28 +0000 raw.test: {"log_level":"WARN","message":"foo bar baz","count":40,"interval":10,"threshold":30}
2016-05-26 11:59:38 +0000 raw.test: {"log_level":"WARN","message":"foo bar baz","count":40,"interval":10,"threshold":30}

gemspecを編集

gemライブラリの依存関係などをgemspecに記載します。
fluent-plugin-grepcount-filter.gemspec
ラベル機能を使いたいため、Fluentd v0.12以上を対象としているため "fluentd", ">= 0.12" としました。

RubyGems.orgにアップロード

プラグインが完成したらRubyGems.orgにアップロードして公開します。RubyGems.orgに予めサインアップしておいてください。

$ export PATH=$PATH:/opt/td-agent/embedded/bin
$ gem install jeweler
$ gem install gemcutter

$ gem build fluent-plugin-grepcount-filter.gemspec
WARNING:  description and summary are identical
WARNING:  open-ended dependency on fluentd (>= 0.12) is not recommended
  if fluentd is semantically versioned, use:
    add_runtime_dependency 'fluentd', '~> 0.12'
WARNING:  See http://guides.rubygems.org/specification-reference/ for help
  Successfully built RubyGem
  Name: fluent-plugin-grepcount-filter
  Version: 0.0.1
  File: fluent-plugin-grepcount-filter-0.0.1.gem

$ rake release
fluent-plugin-grepcount-filter 0.0.1 built to pkg/fluent-plugin-grepcount-filter-0.0.1.gem.
Tagged v0.0.1.
Pushed git commits and tags.
Pushed fluent-plugin-grepcount-filter 0.0.1 to rubygems.org.

アップロードが完了すると、RubyGemsに公開されます。
https://rubygems.org/gems/fluent-plugin-grepcount-filter

試しにgem installでインストールできるかを確認します。

$ export PATH=$PATH:/opt/td-agent/embedded/bin
$ gem install fluent-plugin-grepcount-filter
Fetching: fluent-plugin-grepcount-filter-0.0.1.gem (100%)
Successfully installed fluent-plugin-grepcount-filter-0.0.1
Parsing documentation for fluent-plugin-grepcount-filter-0.0.1
Installing ri documentation for fluent-plugin-grepcount-filter-0.0.1
Done installing documentation for fluent-plugin-grepcount-filter after 0 seconds
1 gem installed

$ gem list | grep fluent-plugin-grepcount-filter
fluent-plugin-grepcount-filter (0.0.1)

インストールできました!

最後に

Fluentdプラグインを作ってRubyGemsに公開してみました。お世辞にもRubyが書けると言えるわけでもなく、とりあえず動くものを作ろうと思い、テストもREADMEも書けていないお粗末なプラグインですが、Total Downloadが400を超えているので誰かしらが使ってくれているのだと思うと嬉しいものです。今後はちゃんとメンテナンスもしていきます。

参考URL