web-dev-qa-db-ja.com

ロガーがクラスごとにロガーの使用を推奨するのはなぜですか?

NLogのドキュメントによると:

ほとんどのアプリケーションは、クラスごとに1つのロガーを使用します。ロガーの名前はクラスの名前と同じです。

これは、log4netの動作と同じです。なぜこれが良い習慣ですか?

86
Daniel T.

Log4netでは、クラスごとに1つのロガーを使用すると、ログメッセージのソース(つまり、クラスがログに書き込む)を簡単にキャプチャできます。クラスごとに1つのロガーがなく、アプリ全体に1つのロガーがある場合、ログメッセージの送信元を知るために、より多くのリフレクショントリックに頼る必要があります。

以下を比較してください。

クラスごとのログ

using System.Reflection;
private static readonly ILog _logger = 
    LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);    

public void SomeMethod()
{
    _logger.DebugFormat("File not found: {0}", _filename);
}

アプリごとに1つのロガー(または同様のもの)

Logger.DebugFormat("File not found: {0}", _filename); // Logger determines caller

-- or --

Logger.DebugFormat(this, "File not found: {0}", _filename); // Pass in the caller

2番目の例を使用すると、ロガーはスタックトレースを作成して、それを呼び出しているユーザーを確認する必要があります。そうしないと、コードは常に呼び出し元を渡す必要があります。クラスごとのロガースタイルでは、これを行うことができますが、呼び出しごとに1回ではなく、クラスごとに1回行うことができ、深刻なパフォーマンスの問題を排除できます。

57
Jeremy Wiebe

NLogで「ファイルごとのロガー」を使用する利点:名前空間とクラス名でログを管理/フィルタリングする可能性があります。例:

<logger name="A.NameSpace.MyClass"      minlevel="Debug" writeTo="ImportantLogs" /> 
<logger name="A.NameSpace.MyOtherClass" minlevel="Trace" writeTo="ImportantLogs" /> 
<logger name="StupidLibrary.*"          minlevel="Error" writeTo="StupidLibraryLogs" />

<!-- Hide other messages from StupidLibrary -->
<logger name="StupidLibrary.*" final="true" /> 

<!-- Log all but hidden messages -->
<logger name="*" writeTo="AllLogs" /> 

NLoggerには、これを行うための非常に便利なコードスニペットがあります。 nloggerスニペットは次のコードを作成します。

private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

そのため、キーストロークはほとんどなく、クラスごとにロガーがあります。ロガーの名前として名前空間とクラス名を使用します。クラスロガーに別の名前を設定するには、これを使用できます:

private static NLog.Logger logger = NLog.LogManager.GetLogger("MyLib.MyName");

そして、@ JeremyWiebeが言ったように、メッセージをログに記録しようとしているクラスの名前を取得するためにトリックを使用する必要はありません:ロガーの名前(通常はクラスの名前)はファイルに簡単に記録できます(または他のターゲット)レイアウトで${logger}を使用して。

15
CoperNick

この選択にはいくつかの理由があります。

  • ログ出力形式にロガーの名前を含めると、特定のログステートメントがどこから来たかを常に知ることができます。
  • 特定のロガーをオンまたはオフにするか、レベルを設定することにより、細かなレベルで表示されるログステートメントを制御できます。
5
Peter Recore

NLogの場合にもパフォーマンス上の利点があります。ほとんどのユーザーが使用します

Logger logger = LogManager.GetCurrentClassLogger()

スタックトレースから現在のクラスをルックアップするには、ある程度のパフォーマンスが必要になります(ただし、それほどではありません)。

4
Julian

ほとんどの場合、クラスの名前はロガーに適切な名前を提供します。ログファイルをスキャンすると、ログメッセージが表示され、コード行に直接関連付けることができます。

これが最良のアプローチではない良い例は、HibernateのSQLログです。 「Hibernate.SQL」などの名前の共有ロガーがあります。このロガーでは、多数の異なるクラスが生のSQLを単一のロガーカテゴリに書き込みます。

3
Eric Hauser

開発の観点からは、毎回ロガーオブジェクトを作成する必要がない場合が最も簡単です。一方、そうしない場合は、リフレクションを使用して動的に作成すると、パフォーマンスが低下します。これを解決するために、ロガーを動的に非同期的に作成する次のコードを使用できます。

using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WinForms
{
    class log
    {

        public static async void Log(int severity, string message)
        {
            await Task.Run(() => LogIt(severity, message));
        }

        private static void LogIt(int severity, string message)
        {
            StackTrace st = new StackTrace();
            StackFrame x = st.GetFrame(2);     //the third one goes back to the original caller
            Type t = x.GetMethod().DeclaringType;
            Logger theLogger = LogManager.GetLogger(t.FullName);

            //https://github.com/NLog/NLog/wiki/Log-levels
            string[] levels = { "Off", "Trace", "Debug", "Info", "Warn", "Error", "Fatal" };
            int level = Math.Min(levels.Length, severity);
            theLogger.Log(LogLevel.FromOrdinal(level), message);

        }
    }
}
2
as9876

すぐに思い浮かぶ2つの理由:

  1. クラスごとに個別のログを作成すると、特定のクラスに関連するすべてのログメッセージ/エラーを簡単にグループ化できます。
  2. クラス内にログを保持すると、クラスの外部からはアクセスできない内部の詳細(プライベート状態、クラスの実装に関する情報など)を記録できます。
1
Dan Tao

おそらく、カプセル化を壊さずにクラスにのみ表示されるメソッドをログに記録したいため、これにより、ロギング機能を壊さずに別のアプリケーションでクラスを簡単に使用できるようになります。

0
Rodrick Chapman

名前空間またはクラスごとにアペンダーを簡単に構成できます。

0
dotjoe

NLOGを使用している場合は、構成で呼び出しサイトを指定できます。これにより、ロギングステートメントが配置されたクラス名とメソッドが記録されます。

<property name="CallSite" value="${callsite}" />

次に、ロガー名またはアセンブリ名に定数を使用できます。

免責事項:NLOGがこの情報を収集する方法はわかりません。私の推測では反映されるため、パフォーマンスを考慮する必要があるかもしれません。 NLOG v4.4以降を使用していない場合、非同期メソッドにはいくつかの問題があります。

0
user6271979