17

アプリで log4net を正常に構成しましたが、1 つのことが少し面倒です。

エラーが発生していなくても、アプリの起動後にログ ファイルが作成されます (空になります)。エラーが発生した場合にのみログファイルを作成したいと思います。

4

7 に答える 7

15

私は実際にこのスレッドでこれを行う方法を見つけました:

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番目の方法は、リンクにリストされています。私はこの手法を試したことはありませんが、技術的には健全なようです。

于 2011-02-11T19:03:58.723 に答える
8

これは古い質問ですが、他の人にも役立つと思います。

エラーが発生しなかった場合にアプリケーションが空のログファイルを残してはならないという同様の状況に遭遇しました。

次のカスタム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クラスから派生しています。

ロックが解除された後もログファイルが空の場合にログファイルを削除する機能を追加しました。これにより、アプリケーションが実行され、エラーなしで終了した場合に、アプリケーションが空のエラーログファイルを残すのを防ぎます。

長所

  • Log4Netの構成フェーズでも空のログファイルが作成され、アプリの残りの部分が起動する前にログが機能していることを確認します。ただし、ログファイルはすぐに削除されます。
  • しきい値を「OFF」に設定して構成ファイルのロギングをオフにする必要はありません。その後、最初のログイベントを書き込む前にプログラムでロギングをオンにします。

短所

  • これは、ログファイルを管理するための遅い方法である可能性があります。これは、ReleaseLockメソッドとファイル長のチェックが、ログファイルに書き込まれるすべてのログイベントの後に呼び出されるためです。エラーが非常に少ないと予想される場合にのみ使用してください。エラーがない場合はログファイルが存在しないことがビジネス要件です。
  • ログファイルは、空のときに作成および削除されます。これは、ファイルシステムの変更についてログディレクトリを監視する他のツールがある場合に問題になる可能性があります。しかし、これは私たちの状況では問題ではありませんでした。
于 2012-08-29T10:05:32.540 に答える
6

以下は私のために働いた. 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 ソースからのシーケンスは次のとおりです。


  • OpenFile() への最初の呼び出しは、FileAppender のコンストラクターから呼び出された ActivateOptions() によるものです。
  • ログ メッセージが生成されると、AppenderSkeleton の DoAppend() は PreAppendCheck() を呼び出します。
  • PreAppendCheck() は、FileAppender のベースである TextWriterAppender でオーバーライドされます。
  • ファイルがまだ開いていない場合、オーバーライドされた PreAppendCheck() は仮想 PrepareWriter を呼び出します。
  • FileAppender の PrepareWriter() は、OpenFile() を呼び出す SafeOpenFile() を呼び出します。
于 2016-02-29T03:23:00.693 に答える
3

このアプローチの問題は、ファイルが存在するが読み取り専用である場合、または存在しないディレクトリにある場合など、別のエラーがすでに問題を引き起こしているまでわからないことです。アプリの残りの部分を開始する前に、ロギングが機能していることを本当に確信したいでしょう。

とにかくこれを行う方法があるかもしれませんが、そうでない場合、これが理由だと思います。

于 2010-03-28T15:32:14.793 に答える
2

非常に簡単な別の方法が、メーリング リスト アーカイブのこのメッセージに記載されています。

基本的に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);

しかし、それを削除し、追加のロジックを使用して上記のゲッターを追加すると、代わりに問題が解決しました。

注: 一般に、ほとんどの場合、アプリケーションの起動時にロガーを構成してファイルを作成 (さらには書き込み) するのが最善であることに同意します。

于 2012-02-08T22:49:05.070 に答える
0

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
于 2014-10-08T20:03:52.023 に答える