fluent-logger-rubyのbufferingを調べてみたよ

概要
----

SMTPでメッセージ転送していた時代では、localhostにSMTPサーバを立てて、そいつにスプール(=buffering)させてました
これはプログラムから直接SMTPサーバ接続する場合にSMTPサーバが落ちてるとそこで処理がブロックされてしまうため、擬似的な非同期化をするための古の知恵でした

Fluentdはlocalhostにfluentdを立てる必要があるのか？という素朴な疑問を調査していたら、結局[fluent-logger-ruby](https://github.com/fluent/fluent-logger-ruby)の実装を調べるということになったので、それのメモ

TL;DR
-----

- fluent-logger-ruby自体にbuffering&retry機構が入っている  
  下記の仕様でOKならlocalhostにFluentdは不要
- bufferサイズは8MB (8,388,608)  
- オーバーフローするとbufferの中身はすべて削除
- retryあるよ

※すべてのfluent-loggerを調べていません。なので、言語実装によってbuffering機構が入っていない・bufferサイズが違うといった事があるかも


Bufferオーバーフロー
--------------------------

Bufferオーバーフローするとbufferの中身は全て消えてしまいます

ただ、その前に`Fluent::Logger::FluentLogger.new` 時に指定した`buffer_overflow_handler` をinvokeできる[機構があります](https://github.com/fluent/fluent-logger-ruby#buffer-overflow)


Bufferサイズ
-----------

`Fluent::Logger::FluentLogger::BUFFER_LIMIT` を上書きすればサイズ変更可能(Rubyがwarning出すけどね)


retry回数と間隔
-------------

(13回で打ち止め、右は間隔)

```
1	0.5s
2	0.8s
3	1.1s
4	1.7s
5	2.5s
6	3.8s
7	5.7s
8	8.5s
9	12.8s
10	19.2s
11	28.8s
12	43.2s
13	64.9s
```

検証コード
--------

```rb
require "fluent-logger"
require "pp"
trap(:INT) { exit }

# すぐオーバーフローさせたかったので小さいサイズにしている(rubyにワーンって言われるよ)
Fluent::Logger::FluentLogger.const_set(:BUFFER_LIMIT, 100)

class BufferOverflowHandler
  attr_accessor :buffer
  def flush(messages)
    @buffer ||= []
    MessagePack::Unpacker.new.feed_each(messages) do |msg|
      @buffer << msg
    end
    pp @buffer
  end
end

handler = Proc.new { |messages| BufferOverflowHandler.new.flush(messages) }
logger = Fluent::Logger::FluentLogger.new("debug", host: "localhost", port: 24224, buffer_overflow_handler: handler)
loop {
  p Time.now.to_s
  logger.post("a", {any: "#{Time.now.to_s}"})
  sleep 1
}
```

結果

```console
$ ruby testing-fluent-logger.rb 
fluent-logger.rb:7: warning: already initialized constant Fluent::Logger::FluentLogger::BUFFER_LIMIT
/home/ma2shita/f/vendor/bundle/ruby/2.3.0/bundler/gems/fluent-logger-ruby-c94649a8468f/lib/fluent/logger/fluent_logger.rb:27: warning: previous definition of BUFFER_LIMIT was here
E, [2016-05-10T14:19:34.987988 #6665] ERROR -- : Failed to connect fluentd: Connection refused - connect(2) for "localhost" port 24224
E, [2016-05-10T14:19:34.988044 #6665] ERROR -- : Connection will be retried.
"2016-05-10 14:19:34 +0900"
"2016-05-10 14:19:35 +0900"
"2016-05-10 14:19:36 +0900"
E, [2016-05-10T14:19:36.989794 #6665] ERROR -- : FluentLogger: Can't send logs to localhost:24224: Connection refused - connect(2) for "localhost" port 24224
[["debug.a", 1462857574, {"any"=>"2016-05-10 14:19:34 +0900"}],
 ["debug.a", 1462857575, {"any"=>"2016-05-10 14:19:35 +0900"}],
 ["debug.a", 1462857576, {"any"=>"2016-05-10 14:19:36 +0900"}]]
"2016-05-10 14:19:37 +0900"
"2016-05-10 14:19:38 +0900"
"2016-05-10 14:19:39 +0900"
E, [2016-05-10T14:19:39.993584 #6665] ERROR -- : FluentLogger: Can't send logs to localhost:24224: Connection refused - connect(2) for "localhost" port 24224
[["debug.a", 1462857577, {"any"=>"2016-05-10 14:19:37 +0900"}],
 ["debug.a", 1462857578, {"any"=>"2016-05-10 14:19:38 +0900"}],
 ["debug.a", 1462857579, {"any"=>"2016-05-10 14:19:39 +0900"}]]
"2016-05-10 14:19:40 +0900"
"2016-05-10 14:19:41 +0900"
"2016-05-10 14:19:42 +0900"
```

何が言いたいかというと
------------------

Fluentdって本体だけでなくて、それを取り巻くツール類もすごいよ！