アプリで log4net を正常に構成しましたが、1 つのことが少し面倒です。
エラーが発生していなくても、アプリの起動後にログ ファイルが作成されます (空になります)。エラーが発生した場合にのみログファイルを作成したいと思います。
アプリで log4net を正常に構成しましたが、1 つのことが少し面倒です。
エラーが発生していなくても、アプリの起動後にログ ファイルが作成されます (空になります)。エラーが発生した場合にのみログファイルを作成したいと思います。
私は実際にこのスレッドでこれを行う方法を見つけました:
http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/postid/18271/view/topic/Default.aspx
最初の方法をテストしましたが、うまくいきました。そのリンクがうまくいかない場合に備えて、ここにコードを再現します。基本的に、著者は、これを行うには 2 つの方法があると述べています。
最初の方法:
そのロガーの適切なしきい値が機能する場合にのみ、ロックを取得 (およびファイルを作成) する新しいロック モデルを作成します。
public class MyLock : log4net.Appender.FileAppender.MinimalLock
{
public override Stream AcquireLock()
{
if (CurrentAppender.Threshold == log4net.Core.Level.Off)
return null;
return base.AcquireLock();
}
}
構成ファイルで、しきい値を次のように設定します。
<threshold value="OFF" />
モデルとして、この新しい LockingModel を必ず設定してください。
<lockingModel type="Namespace.MyLock" />
これをローリングファイルアペンダーで使用しています。
2番目の方法は、リンクにリストされています。私はこの手法を試したことはありませんが、技術的には健全なようです。
これは古い質問ですが、他の人にも役立つと思います。
エラーが発生しなかった場合にアプリケーションが空のログファイルを残してはならないという同様の状況に遭遇しました。
次のカスタムLockingModelクラスを作成することで解決しました。
public class MinimalLockDeleteEmpty : FileAppender.MinimalLock
{
public override void ReleaseLock()
{
base.ReleaseLock();
var logFile = new FileInfo(CurrentAppender.File);
if (logFile.Exists && logFile.Length <= 0)
{
logFile.Delete();
}
}
}
これは、各ログメッセージの書き込み後にログファイルのロックを解放するFileAppender.MinimalLockクラスから派生しています。
ロックが解除された後もログファイルが空の場合にログファイルを削除する機能を追加しました。これにより、アプリケーションが実行され、エラーなしで終了した場合に、アプリケーションが空のエラーログファイルを残すのを防ぎます。
長所
短所
以下は私のために働いた. OpenFile() への最初の呼び出しは、ロガーが設定されたときに発生します。後続の呼び出しは、実際のログ メッセージが生成されるときです。
class CustomFileAppender : RollingFileAppender
{
private bool isFirstTime = true;
protected override void OpenFile(string fileName, bool append)
{
if (isFirstTime)
{
isFirstTime = false;
return;
}
base.OpenFile(fileName, append);
}
}
そして、設定ファイルで、アペンダーを変更します
<log4net>
<appender name="RollingFile" type="<your namespace>.CustomFileAppender">
...
</log4net>
log4Net ソースからのシーケンスは次のとおりです。
このアプローチの問題は、ファイルが存在するが読み取り専用である場合、または存在しないディレクトリにある場合など、別のエラーがすでに問題を引き起こしているまでわからないことです。アプリの残りの部分を開始する前に、ロギングが機能していることを本当に確信したいでしょう。
とにかくこれを行う方法があるかもしれませんが、そうでない場合、これが理由だと思います。
非常に簡単な別の方法が、メーリング リスト アーカイブのこのメッセージに記載されています。
基本的にlog4netでは、ロガーの設定時にログファイルが作成されます。そうしないように設定するのは少しハックです。解決策は、構成の実行を延期することです。上記のメッセージは、ロガーを設定するときに次のことを行うことを提案しています。
private static ILog _log = LogManager.GetLogger(typeof(Program));
public static ILog Log
{
get
{
if(!log4net.LogManager.GetRepository().Configured)
log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
return _log;
}
}
私は通常、log4net をassembly属性で構成します。これにより、ロガーが自動的に構成され (したがって、ログ ファイルが作成されます)、ログの単純なゲッターが作成されます。
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
...
public static log4net.ILog Log { get { return _log; } }
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
しかし、それを削除し、追加のロジックを使用して上記のゲッターを追加すると、代わりに問題が解決しました。
注: 一般に、ほとんどの場合、アプリケーションの起動時にロガーを構成してファイルを作成 (さらには書き込み) するのが最善であることに同意します。
AcquireLock および ReleaseLock メソッドは私にとってはうまくいきましたが、ファイルが何度も作成/削除されたことが気になりました。プログラムの完了時にロガーをシャットダウンし、空のログファイルを削除する別の同様のオプションを次に示します。ロギングが完了したら、RemoveEmptyLogFile を呼び出すだけです。
/// <summary>
/// Sets the logging level for log4net.
/// </summary>
private static void RemoveEmptyLogFile()
{
//Get the logfilename before we shut it down
log4net.Appender.FileAppender rootAppender = (log4net.Appender.FileAppender)((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root.Appenders[0];
string filename = rootAppender.File;
//Shut down all of the repositories to release lock on logfile
log4net.Repository.ILoggerRepository[] repositories = log4net.LogManager.GetAllRepositories();
foreach (log4net.Repository.ILoggerRepository repository in repositories)
{
repository.Shutdown();
}
//Delete log file if it's empty
var f = new FileInfo(filename);
if (f.Exists && f.Length <= 0)
{
f.Delete();
}
} // RemoveEmptyLogFile