3

ロギングアプリケーションとして多くの考慮を払ってlog4Netを選択したので、それについての議論はしないでください

OK、聞いて私の問題です

  • 単一のプロセスを複数のクライアントに接続しました
  • 各クライアントには、独自の個別のスレッドに文字列として格納された一意のIDがあります
  • 同じ一意のIDを持つ各クライアントは、複数回接続できます

  • クライアントごとに異なる.txtファイルでログファイルを作成したいと思います。

  • 新しい接続ごとに、クライアントIDに日時と秒を追加したログファイルを作成したい

このシナリオでは、アプリケーションの以前のロギング経験がまったくないため、混乱しました。

私は私のシナリオを十分に明確にしたことを願っています:)

4

2 に答える 2

3

これは、リクエストを独自のファイルに書き込む方法についての質問には答えませんが、log4netヘルプは特に単純なアプローチを推奨しています。ThreadContext.Propertiesオブジェクトおよびその他のプロパティを使用して、ログメッセージを装飾し、各要求からメッセージを区別できるようにします。

http://logging.apache.org/log4net/release/faq.html

「複数のクライアント要求の出力を異なるログファイルに送信できますか?」を参照してください。

クライアントIDをお持ちの場合は、次のようなことを行うことができます。

log4net.ThreadContext.Properties["ClientID"] = GetTheClientId();

パターンレイアウトでは、次のようなことができます。

<conversionPattern value="%date [%thread] %-5level %logger [%property{ClientID}] - %message%newline" />

%property{ClientID}ThreadContextからClientIDをどこにプルしますか。

これにより、ログに記録された各メッセージに関連するClientIDのタグが付けられます。

log4netコンテキストオブジェクトの使用に関する優れたチュートリアルについては、次のリンクを参照してください。

http://www.beefycode.com/post/Log4Net-Tutorial-pt-6-Log-Event-Context.aspx

log4netチュートリアル全体は、特にlog4netを使い始めたばかりの場合は、非常に優れています。

これがパート1です。

http://www.beefycode.com/post/Log4Net-Tutorial-pt-1-Getting-Started.aspx

そうは言っても、次のリンクで説明されているように、人々はしばしばGlobalContextオブジェクトを使用して出力ファイルに名前を付けます。

http://geekswithblogs.net/rgupta/archive/2009/03/03/dynamic-log-filenames-with-log4net.aspx

GlobalContextを介して出力ファイルに名前を付けるプロセスを見たときはいつでも、推奨される解決策は、log4netが実際に開始する前に必ずGlobalContext.Properties["whatever"]値を設定するように指示します。これにより、ThreadContextに動的に格納されている情報に基づいて個々のログファイルを作成することは、不可能ではないにしても難しいと思います。その情報は、log4netがすでに実行されるまでわからない可能性があるためです。

[アップデート]

これは、ここからSOにある別のリンクで、GlobalContextの値の出力ファイルに名前を付ける方法を示しています。ここでも、filenameの基になる値は、log4netを構成する前、およびロガーを取得する前に、GlobalContextに設定する必要があることに注意してください。

log4netアペンダー名でGlobalContextプロパティを使用するにはどうすればよいですか?

上で述べたように、そして私のコメントで、log4netがThreadContextの値またはスレッドIDによって指定された出力ファイル名で(同じFileAppender構成に対して)複数の出力ファイルを作成できるかどうかはわかりません財産。たぶん、log4netに精通している他の誰かがそれを検討することができます。

そうは言っても、NLogでこれを正確に行うことは可能です。これは、名前の一部がスレッドIDから派生したファイルターゲットを定義するNLog構成です(${threadid}構成のfileName部分に注意してください)。

<targets>
    <target name="file" xsi:type="File" layout="${longdate} | ${processid} | ${threadid} | ${logger} | ${level} | ${message}" fileName="${basedir}/log_${threadid}.txt" />
</targets>

次のコードで:

  class Program
  {
    public static Logger logger = LogManager.GetCurrentClassLogger();

    static void Main(string[] args)
    {

      int totalThreads = 20;
      TaskCreationOptions tco = TaskCreationOptions.None;
      Task task = null;

      logger.Info("Enter Main");

      Task[] allTasks = new Task[totalThreads];
      for (int i = 0; i < totalThreads; i++)
      {
        int ii = i;
        task = Task.Factory.StartNew(() =>
        {
          logger.Info("Inside delegate.  i = {0}", ii);
        });

        allTasks[i] = task;
      }

      logger.Info("Wait on tasks");

      Task.WaitAll(allTasks);

      logger.Info("Tasks finished");

      logger.Info("Exit Main");
    }
  }

4つのログファイルを取得しました。各ログファイルの名前にはスレッドIDが含まれ、各ログファイルには単一のスレッドからのメッセージのみが含まれていました。

同様に、この構成では(注${mdc:item=id}):

<targets>
    <target name="file" xsi:type="File" layout="${longdate} | ${processid} | ${threadid} | ${logger} | ${level} | ${message}" fileName="${basedir}/log_${mdc:item=id}.txt" />
</targets>

そしてこのコード:

  class Program
  {
    public static Logger logger = LogManager.GetCurrentClassLogger();

    static void Main(string[] args)
    {

      int totalThreads = 20;
      TaskCreationOptions tco = TaskCreationOptions.None;
      Task task = null;

      logger.Info("Enter Main");

      Task[] allTasks = new Task[totalThreads];
      for (int i = 0; i < totalThreads; i++)
      {
        int ii = i;
        task = Task.Factory.StartNew(() =>
        {
          MDC.Set("id",Thread.CurrentThread.ManagedThreadId.ToString());
          logger.Info("Inside delegate.  i = {0}", ii);
        });

        allTasks[i] = task;
      }

      logger.Info("Wait on tasks");

      Task.WaitAll(allTasks);

      logger.Info("Tasks finished");

      logger.Info("Exit Main");
    }
  }

MDC(log4netのThreadContext.Propertiesオブジェクトに相当するNLog)に格納されている値に基づいて、複数の出力ファイルを取得できます。

于 2011-01-31T15:46:08.277 に答える
2

すべての回答とヘルプをありがとうございますが、たくさんの検索を行った後、最終的に答えが見つかりました....複数のファイルを作成できるだけでなく、動的なファイル名を使用できます。これが皆さんにも役立つことを願っています:)

誰もが言っているように、1つのアペンダーが1つのファイル名に関連付けられているため、1つのアペンダーに動的なファイル名を付けることはできても、N個のファイル名を付けることはできないため、構成ファイルに基づくことはできません。

だから私の設定は次のとおりです

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

  <log4net>
  </log4net>

</configuration>

[更新]:実際には、構成は必要ありませんはい、動的構成を作成する予定なので、構成は空です。

コードは次のとおりです。

主要:

SetLevel(clientID, "ALL");
AddAppender(clientID, CreateFileAppender(clientID, fileName));

ILog log = LogManager.GetLogger(clientID);
log.Any("whatever you want");

関数:

public static log4net.Appender.IAppender CreateFileAppender(string name, string fileName)
{
      log4net.Appender.FileAppender appender = new
      log4net.Appender.FileAppender();
      appender.Name = name;
      appender.File = fileName;
      appender.AppendToFile = false;

      log4net.Layout.PatternLayout layout = new
      log4net.Layout.PatternLayout();
      layout.ConversionPattern = "%d [%thread] %-5p %c [%a] - %m [%line] [%M]%n";
      layout.ActivateOptions();

      appender.Layout = layout;
      appender.ActivateOptions();

      return appender;
}

public static void SetLevel(string loggerName, string levelName)
{
      log4net.ILog log = log4net.LogManager.GetLogger(loggerName);
      log4net.Repository.Hierarchy.Logger l = (log4net.Repository.Hierarchy.Logger)log.Logger;

      l.Level = l.Hierarchy.LevelMap[levelName];
}

// Add an appender to a logger
public static void AddAppender(string loggerName, log4net.Appender.IAppender appender)
{
      log4net.ILog log = log4net.LogManager.GetLogger(loggerName);
      log4net.Repository.Hierarchy.Logger l=(log4net.Repository.Hierarchy.Logger)log.Logger;
      l.AddAppender(appender);
}

ここで、指定した名前でロガーを作成し、任意のスレッドまたはクラスでいつでもどこでもそれをフェッチします。作成したアペンダーをフェッチし、必要に応じてコマンドを使用して変更することもできます。

     log4net.LogManager.GetRepository().GetAppenders()

そしてそれを繰り返します。つまり、実際にはすべてが動的です:)

Woopsが元のソースを追加するのを忘れた: Log4NetMailアーカイブ

于 2011-02-02T05:18:24.763 に答える