datadog の ruby ライブラリ dogapi で batch_metrics をネストするとダメそう

NOTE: v1.3.0 で見てます。

先日 datadog にメトリクスなげてーなと思ったのでライブラリの使い方を見てたのですがあんまり出来がよくなさそうです。気になったのはここ。

dog.batch_metrics do
  dog.emit_point('test.api.test_metric',10)
  dog.emit_point('test.api.this_other_metric', 1, :type => 'counter')
end

docs.datadoghq.com

batch_metrics というメソッド自体は、1回1回リクエストを投げずにためて投げるというやつですね。ふつーのバッチ処理

ですが、サンプルコードを見ただけでなんとなーくあやしい感じがします。内部実装を素直に予想するとこんな感じになりそうですね。

def batch_metrics
  @batch_mode = true # 逐次で投げないようにするフラグ
  yield
  @batch_mode = false
  flush! # ここでためたのを投げる
end

でもこれだとこういうときに困りそうです。手元で spec 書いたら落ちるしたぶんダメ。

dog.batch_metrics do
  # @batch_mode = true になる
  dog.batch_metrics do
    dog.emit_point('test.api.test_metric',10)
  end
  # @batch_mode = false になってしまう
  dog.emit_point('test.api.this_other_metric', 1, :type => 'counter') # 逐次で送られるんじゃね?
end

実際には @buffernil かどうかで同じようなことをやっています。このへんを参照。

https://github.com/DataDog/dogapi-rb/blob/d66698a363ae851845525d30a7d6a8afa1927dc5/lib/dogapi/facade.rb#L108-L116

https://github.com/DataDog/dogapi-rb/blob/d66698a363ae851845525d30a7d6a8afa1927dc5/lib/dogapi/v1/metric.rb#L52-L58

これより良さそうな API もあって、こんな感じ。

dog.batch_metrics do |batch_dog| # バッチリクエスト用のクライアントを返す
  batch_dog.emit_point('test.api.test_metric',10)
  batch_dog.batch_metrics do |batch_dog2| # batch_dog と batch_dog2 は同じものを返せばよい
    batch_dog.emit_point('test.api.test_metric',10)
  end
  # 最初の block から抜けるときに作られたものを flush すればよい
end

というのでなんかよくできるんじゃないかなーとプロジェクトを見てたら rspec なのに let 使ってなかったりでちょっと心が折れた日曜日なのでした。

まあ実際こういうの送るときにネストしたりしないからこまんないような気もしますね