Log4netのFileAppenderでファイル名を動的に変更する(リフレイン)
先月書いた、標題のエントリだが、同一アセンブリを起動した場合、問題が発生することが発覚した。同エントリ中、サンプルコードで示したFileAppender.Fileを置き換えて、ActivateOptionsを呼ぶ部分だが
fileAppender.File = file.Replace("MyApp", entryAsm.GetName().Name); fileAppender.ActivateOptions();
このとき、既に同一のアセンブリが起動している、つまり同一のファイル名を使っている場合、ActivateOptionsメソッドの行内で例外が発生する。
System.ArgumentException が発生しました。 Message="ストリームに書き込めませんでした。" Source="mscorlib" StackTrace: 場所 System.IO.StreamWriter..ctor(Stream stream, Encoding encoding, Int32 bufferSize)
これは、FileAppenderがデフォルトで使用しているロックモデル(LockModel)が排他的ロック(FileAppender.ExclusiveLock)を使用しており、アセンブリの実行中は(ファイルのオープン中は)排他的にオープンしているからだ。とりあえず同一のファイルを開くことを許可するためには、FileAppenderのロックモデルをより緩いものに変える必要がある。
fileAppender.File = file.Replace("MyApp", entryAsm.GetName().Name);
fileAppender.LockingModel = new log4net.Appender.FileAppender.MinimalLock();
fileAppender.ActivateOptions();
これでアセンブリが複数起動してもログファイルは開けるようになるが、この場合、複数の同一名を持つアセンブリが同一のログファイルにログを書き込むため、ここを上手く制御しないと、例えば時系列のログとしての実効性が無くなる可能性がある。従って、これが最良の解決方法か否かは今後検証の予定。
追記:
FileAppender.LockingModelに関しては、設定ファイルで最初からMimalLockを指定することもできる。