89

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

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

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

4

10 に答える 10

62

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 番目の例を使用すると、Logger はスタック トレースを作成して呼び出し元を確認する必要があります。そうしないと、コードは常に呼び出し元を渡す必要があります。クラスごとのロガー スタイルでもこれを行うことができますが、呼び出しごとに 1 回ではなく、クラスごとに 1 回実行することで、深刻なパフォーマンスの問題を解消できます。

于 2010-06-29T19:18:27.253 に答える
5

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

  • ログ出力形式にロガーの名前を含めると、特定のログ ステートメントがどこから来たのかを常に知ることができます。
  • 特定のロガーをオンまたはオフにするか、それらのレベルを設定することにより、詳細なレベルで表示されるログ ステートメントを制御できます。
于 2010-06-29T19:16:18.843 に答える
4

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

Logger logger = LogManager.GetCurrentClassLogger()

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

于 2016-01-11T23:29:59.453 に答える
3

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

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

于 2010-06-29T19:16:41.153 に答える
1

2 つの理由がすぐに思い浮かびます。

  1. クラスごとに個別のログを作成すると、特定のクラスに関連するすべてのログ メッセージ/エラーを簡単にグループ化できます。
  2. クラス内にログを保持することで、クラス外ではアクセスできない可能性がある内部の詳細をログに記録できます (プライベート ステート、クラスの実装に関する情報など)。
于 2010-06-29T19:15:44.243 に答える
1

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

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);

        }
    }
}
于 2016-01-19T19:45:11.270 に答える
0

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

于 2010-06-29T19:15:05.833 に答える
0

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

于 2010-06-29T19:20:06.260 に答える