.NET でロギングする方法はたくさんあります。一から自分でロギング用クラスを作るなり、System.IO.Log 名前空間内のクラスを使用するなり、log4netNLog 等のライブラリを使用するなり。log4net は歴史がありますしユーザーも多いので安心して使えます。

しかしこの log4net 、非同期的にログ出力してくれるメソッドがデフォルトで用意されていないんですね。基となっている log4j なら AsyncAppender というものがあるらしいのですが……。

たいして時間がかかるわけじゃないとはいえ回数が多ければそれだけ無駄になりますし、ロギングにかかるオーバーヘッドは基本的にプログラムの本質的な部分ではないのでできるだけ小さくしたいと思うわけです。よりリアルタイムに動作する必要があるプログラムであればなおさら。あるいはプログラムが非同期/並列化されていたら、出力処理がたまって出力処理にどんどん時間がかかってしまうなんてことがあるかも。

log4net の各クラスの大体の public 静的メンバはスレッドセーフだと保証されているのでじゃあ自分で非同期出力用のメソッドを作れば良いかという気はするのですが、どうせなら非同期 Appender と Forwarder がほしい。それさえあれば設定ファイルを書き換えるだけで、ソースコードには影響せず、非同期化がすみますから。

そういうわけで探したら一瞬で見つかりました。持つべきものは友(インターネット)です。

cjbhaines/Log4Net.Async

Nuget パッケージが提供されているのでそれを使うと便利です。

PM> Install-Package Log4Net.Async

log4net も Nuget で提供されてますしまとめて追加しちゃえば楽です。

このライブラリの中には log4net 用の非同期な Appender と Forwarder がいくつか入っているので設定ファイルを少し書き換えるだけで使用できます。

短期間に大量のログを出力しようとするとバッファオーバーフローを起こしますので、その辺は注意してください。QueueSizeLimit を増やせば(デフォルトでは1000)蓄えられるバッファのサイズは増やせますが、増やしすぎた場合どのような悪影響があるかはわからないです。

下記は「これまで使用していた log4net.Appender.RollingFileAppender を非同期版に変えたい。ついでに QueueSizeLimit を 2000 にしたい」という場合の例です。