[2016-06-13-1]
にも書いたとおり、こちらの PR で fluent-logger-ruby
を導入しました。
fluentd にも POST する by masutaka · Pull Request #40 · masutaka/masutaka-metrics
その時に、こんな問題に気づきました。
あれ、fluent-logger-ruby って td-agent (reload|restart) したら、コネクション切れちゃうの? post の結果が false だったら、new して post する Wrapper を書かないとダメ?
— マスタカ (@masutaka) June 12, 2016
結論から言うと、Wrapper を作る必要はありません(一度作ってしまった
けど…
)。fluent-logger-ruby がいい感じに処理してくれます。
fluent-logger-ruby の基本的な使い方は、プログラム開始時に #new し
てインスタンスを保持し、あとは必要な時に #post を呼ぶだけです。
class Masutaka
def initialize
@fluent_logger = ::Fluent::Logger::FluentLogger.new
end
def hoge
metrics = { 'field1' => 'hogehoge' }
@fluent_logger.post('masutaka.metrics', metrics)
end
end
プログラム稼働中に fluentd が restart または reload すると、
fluentd との接続は切れてしまいます。#post も false を返し送信して
くれません。でも、あまり気にする必要はありません。
なぜ気にする必要がないか、パターンをまとめました。登場するメソッド
は全て Fluent::Logger::FluentLogger class
にあります。
プログラム稼働中に fluentd を再起動する
- プログラムが起動し、fluent-logger が new される
- fluentd が reload または restart される
- 直後に #post が呼ばれても、fluentd と通信ができず false を返す
- 再度 #post が呼ばれると、↑ここで送れなかったデータとともに fluentd に送信し、true を返す
コードはこちらになります(※)。
https://github.com/fluent/fluent-logger-ruby/blob/v0.5.1/lib/fluent/logger/fluent_logger.rb#L152-L181
fluent-logger は常にデータを @pending に入れて、fluentd に送信しま
す。失敗しても @pending は破棄されず、次回の #post に持ち越されます。
失敗したタイミングでコネクションを閉じる(@con.close)ため、次回
#send_data のこの条件に入り、fluentd と再接続されるという仕組みです。
https://github.com/fluent/fluent-logger-ruby/blob/v0.5.1/lib/fluent/logger/fluent_logger.rb#L185-L187
※ Monitor#synchronize
で括ってあるので、マルチスレッドで同時実行
されないことも保証されてますね。
@pending にデータがある状態でプログラムを正常停止する
プログラム停止時に #close が実行されることが保証されているため、こ
ちらのケースも問題ありません。
https://github.com/fluent/fluent-logger-ruby/blob/v0.5.1/lib/fluent/logger/fluent_logger.rb#L88
Kernel.#at_exit
は Ruby の組み込みメソッドです。正常終了時にブロッ
クが評価されます。
@pending にデータがある状態でプログラムを異常停止する
kill -9 などで異常停止したケースでは救えません。Kernel.#at_exit と
しても、UNIX プログラムとしても正しい動作です。
まとめ
これから fluent-logger-ruby をバリバリ使っていきます!