ベストアンサー1
これらの一部は、厳密な構成の提案ではなく、一般的な NLog (またはログ記録) のヒントのカテゴリに分類されます。
SO からの一般的なログ記録リンクをいくつか示します (これらの一部またはすべては既にご覧になっているかもしれません)。
ロガーではクラスごとにロガーを使用することを推奨するのはなぜですか?
クラスに基づいてロガーに名前を付ける一般的なパターンを使用しますLogger logger = LogManager.GetCurrentClassLogger()
。これにより、ロガーの粒度が高くなり、ロガーの構成の柔軟性が向上します (グローバル、名前空間別、特定のロガー名別など)。
適切な場合は、クラス名ベースではないロガーを使用します。ログ記録を個別に制御したい関数が 1 つあるかもしれません。また、横断的なログ記録 (パフォーマンス ログ記録) に関する懸念があるかもしれません。
クラス名ベースのログ記録を使用しない場合は、構成の柔軟性を高めるために、ロガーに何らかの階層構造 (機能領域別など) で名前を付けることを検討してください。たとえば、「データベース」機能領域、「分析」FA、「UI」FA があるとします。これらのそれぞれにサブ領域がある可能性があります。そのため、次のようにロガーをリクエストできます。
Logger logger = LogManager.GetLogger("Database.Connect");
Logger logger = LogManager.GetLogger("Database.Query");
Logger logger = LogManager.GetLogger("Database.SQL");
Logger logger = LogManager.GetLogger("Analysis.Financial");
Logger logger = LogManager.GetLogger("Analysis.Personnel");
Logger logger = LogManager.GetLogger("Analysis.Inventory");
などなど。階層ロガーを使用すると、ログ記録をグローバル (「*」またはルート ロガー)、FA (データベース、分析、UI)、またはサブエリア (Database.Connect など) ごとに構成できます。
ロガーには多くの設定オプションがあります。
<logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" />
<logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" />
<logger name="Name.Space.*" writeTo="f3,f4" />
<logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" />
を参照してくださいNLogヘルプ各オプションの意味の詳細については、こちらをご覧ください。おそらくここで最も注目すべき点は、ワイルドカード ロガー ルールの機能、単一のログ ステートメントに対して複数のロガー ルールを「実行」できるという概念、およびロガー ルールを「最終」としてマークして、特定のログ ステートメントに対して後続のルールが実行されないようにできることです。
GlobalDiagnosticContext、MappedDiagnosticContext、および NestedDiagnosticContext を使用して、出力に追加のコンテキストを追加します。
簡素化するには、構成ファイルで「変数」を使用します。たとえば、レイアウトを直接指定するのではなく、レイアウトの変数を定義して、ターゲット構成でその変数を参照することができます。
<variable name="brief" value="${longdate} | ${level} | ${logger} | ${message}"/>
<variable name="verbose" value="${longdate} | ${machinename} | ${processid} | ${processname} | ${level} | ${logger} | ${message}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${shortdate}.log" />
<target name="console" xsi:type="ColoredConsole" layout="${brief}" />
</targets>
または、レイアウトに追加する「カスタム」プロパティ セットを作成することもできます。
<variable name="mycontext" value="${gdc:item=appname} , ${mdc:item=threadprop}"/>
<variable name="fmt1withcontext" value="${longdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>
<variable name="fmt2withcontext" value="${shortdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>
または、構成を介して厳密に「日」または「月」レイアウト レンダラーを作成するなどの操作を行うこともできます。
<variable name="day" value="${date:format=dddd}"/>
<variable name="month" value="${date:format=MMMM}"/>
<variable name="fmt" value="${longdate} | ${level} | ${logger} | ${day} | ${month} | ${message}"/>
<targets>
<target name="console" xsi:type="ColoredConsole" layout="${fmt}" />
</targets>
レイアウト レンダリングを使用してファイル名を定義することもできます。
<variable name="day" value="${date:format=dddd}"/>
<targets>
<target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${day}.log" />
</targets>
ファイルを毎日ロールする場合、各ファイルの名前は「Monday.log」、「Tuesday.log」などになります。
独自のレイアウト レンダラーを作成することをためらわないでください。これは簡単で、構成を介してログ ファイルに独自のコンテキスト情報を追加できます。たとえば、Trace.CorrelationManager.ActivityId をログに追加できるレイアウト レンダラー (NLog 2.0 ではなく 1.x ベース) は次のとおりです。
[LayoutRenderer("ActivityId")]
class ActivityIdLayoutRenderer : LayoutRenderer
{
int estimatedSize = Guid.Empty.ToString().Length;
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(Trace.CorrelationManager.ActivityId);
}
protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
{
return estimatedSize;
}
}
次のように、NLog 拡張機能の場所 (どのアセンブリか) を NLog に伝えます。
<extensions>
<add assembly="MyNLogExtensions"/>
</extensions>
カスタム レイアウト レンダラーを次のように使用します。
<variable name="fmt" value="${longdate} | ${ActivityId} | ${message}"/>
非同期ターゲットを使用する:
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
デフォルトのターゲット ラッパー:
<nlog>
<targets>
<default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
</targets>
<targets>
<default-wrapper xsi:type="AsyncWrapper">
<wrapper xsi:type="RetryingWrapper"/>
</default-wrapper>
<target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
<target name="n2" xsi:type="Network" address="tcp://localhost:4002"/>
<target name="n3" xsi:type="Network" address="tcp://localhost:4003"/>
</targets>
</nlog>
適切な場合。詳細については、NLog のドキュメントを参照してください。
NLog に、設定が変更された場合に監視して自動的に再読み込みするように指示します。
<nlog autoReload="true" />
NLogのトラブルシューティングに役立つ設定オプションがいくつかあります。
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
<nlog internalLogToConsole="false|true" />
<nlog internalLogToConsoleError="false|true" />
詳細については、NLog ヘルプを参照してください。
NLog 2.0 では、レイアウト レンダラーの出力に対して追加の処理 (空白のトリミング、大文字化、小文字化など) を実行できるようにする LayoutRenderer ラッパーが追加されました。
コードを NLog への強い依存から切り離したい場合は、ロガーをラップすることを恐れないでください。ただし、正しくラップしてください。NLog の github リポジトリには、ラップ方法の例があります。ラップするもう 1 つの理由は、ログに記録された各メッセージに特定のコンテキスト情報を自動的に追加したい場合です (LogEventInfo.Context に配置することによって)。
NLog (または他のログ フレームワーク) をラップ (または抽象化) することには、長所と短所があります。少し努力すれば、両方の側面を紹介する SO の多くの情報を見つけることができます。
ラッピングをお考えの場合は、共通.ログ記録非常にうまく機能し、必要に応じて別のログ フレームワークに簡単に切り替えることができます。また、ラッピングを検討している場合は、コンテキスト オブジェクト (GDC、MDC、NDC) の処理方法についても検討してください。Common.Logging は現在、それらの抽象化をサポートしていませんが、追加される機能のキューに入っていると思われます。