Go の有名なロギングライブラリ uber-go/zap にて、短時間に同一のログを出力しようとしたときに期待よりも出力される量が少ないことがあった。
具体的には、Webサーバーでアクセスログを出力しているのだが、実際にアクセスされた量よりもログの量が少なかった。
再現
理由
https://github.com/uber-go/zap/blob/master/FAQ.md#why-are-some-of-my-logs-missing に書いてある。
CPU使用量やI/O回数を減らしてパフォーマンスへの影響を減らすためにこうしている。
サンプリングの設定値を変更する
zap.NewProductionConfig()
で SamplingConfig{Initial: 100, Thereafter: 100}
を渡している。
https://github.com/uber-go/zap/blob/d27427d23f81dba1f048d6034d5f286572049e1e/config.go#L157
ちなみに zap.NewDevelopmentConfig()
ではこれが設定されていない気づくのが遅れた。
zap.Config.Sampling
をnilにすると設定が無効になる。
期待値通りの件数が出力される。
各設定値について
Initial
, Thereafter
の設定値はそれぞれ次のような意味になる
Initial
同一のログレベルとメッセージを持つ最初のN件のエントリは出力する
Thereafter
その後の同一のログレベルとメッセージを持つエントリは、M件おきに出力し残りはドロップする
よって次のようにした場合、最初の50件 + 残りの50件は6件おきとなり合計58件出力される。
その他の設定
他にもサンプリング時に実行されるHookを登録したり、サンプリング間隔(デフォルトは1秒)を変更したりもできる。詳細はgodoc
フィールドの変化は同一のログとみなされる
フィールドを可変にしても、メッセージが同じ場合はサンプリングされる
⇒ 58件
1秒時間を空けるとリセットされる
⇒ 116件