NLog:ルールとフィルター

NLog:ルールとフィルター



Confirmitでは、 .NETアプリケーションへのログインにNLogライブラリを使用します。 このライブラリにはドキュメントがありますが、すべてがどのように機能するかを理解することは困難でした。 この記事では、NLogでルールとフィルターがどのように適用されるかを説明します。 始めましょう。







NLogを構成する方法



そして、NLog構成で何ができるかを少し思い出してみましょう。 最も単純な場合、この構成はXMLファイル(たとえば、NLog.config)です。







<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="target1" xsi:type="ColoredConsole" layout="Access Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="red"/> </target> <target name="target2" xsi:type="ColoredConsole" layout="Common Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="green"/> </target> <target name="target3" xsi:type="ColoredConsole" layout="Yellow Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="yellow"/> </target> </targets> <rules> <logger name="*" minlevel="Warn" writeTo="target1,target2,target3" /> </rules> </nlog>
      
      





このファイルは、1行のコードでダウンロードできます。







 LogManager.Configuration = new XmlLoggingConfiguration("NLog.config");
      
      





それで何ができますか? いくつかのメッセージレシーバー(ターゲット)をルールに設定できます。







 <rules> <logger name="*" minlevel="Warn" writeTo="target1,target2,target3" /> </rules>
      
      





このルールが適用されるロギングのレベルを決定できます。







 <rules> <logger name="*" minlevel="Warn" writeTo="target1" /> <logger name="*" levels="Debug,Warn,Info" writeTo="target2" /> </rules>
      
      





各ルールにフィルターを設定できます。







 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <filters defaultAction='Log'> <when condition="contains('${message}','Common')" action="Ignore" /> </filters> </logger> </rules>
      
      





最後に、ネストされたルールを定義できます。







 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <logger name="*" minlevel="Warn" writeTo="target2" /> </logger> </rules>
      
      





すべてがどのように機能するかを調べる時が来ました。







ロガー構成の作成



ロガーインスタンスをリクエストすると、







 var commonLogger = LogManager.GetLogger("Common");
      
      





NLogはキャッシュから既存のものを取得するか、新しいものを作成します( こちらを参照)。 後者の場合、指定された名前のロガーの構成も作成されます。 それを作成するプロセスを見てみましょう。







要するに、ロガー構成は、レシーバーと、各ロギングレベル( Trace



Debug



Info



Warn



Error



Fatal



)に対応するフィルターの別個のチェーンです( こちらを参照)。 次に、これらのチェーンがどのように構築されるかを示します。







これらのチェーンを作成する主なメソッドは、LogFactoryクラスのGetTargetsByLevelForLoggerです。 これがその仕組みです。 NLog構成で指定されたすべてのルールが順番に選択されます。 まず、ルール名がロガー名と一致するかどうかを確認します。 ルール名には、ファイルシステムオブジェクトに使用するものと同じワイルドカードを含めることができます。









したがって、ルール名「 *



」は任意のロガー名と一致し、「 Common*



」は名前が「 Common



」で始まるすべてのロガーと一致します。







ルール名がロガー名と一致しない場合、このルールは破棄され、すべてのルールが埋め込まれます。 それ以外の場合、 GetTargetsByLevelForLogger



メソッドは、このルールが有効になっているすべてのログレベルを取得します。 そのようなレベルごとに、NLogは、ルールで指定されたすべてのメッセージレシーバーを、このルールのフィルターとともに対応するレシーバーチェーンに追加します。







レシーバーチェーンの構築には別の重要な機能があります。 現在のルールがfinal



としてマークされ、その名前がロガーの名前と一致する場合、NLogはこのルールに含まれるすべてのログレベルのチェーンの構築を完了します。 これは、ネストされたルールも後続のルールもこれらのレシーバーチェーンに何も追加しないことを意味します。 それらの作成は完全に完了し、変更されません。 したがって、次のようなものを書くのは意味がありません。







 <rules> <logger name="*" minlevel="Info" writeTo="target1" final="true"> <logger name="*" minlevel="Warn" writeTo="target2" /> </logger> </rules>
      
      





メッセージはtarget2



に到達しません。 しかし、次のようなものを書くことは可能です。







 <rules> <logger name="*" minlevel="Warn" writeTo="target1" final="true"> <logger name="*" minlevel="Info" writeTo="target2" /> </logger> </rules>
      
      





Info



レベルでは外部ルールが有効になっていないため、このレベルの受信者のチェーンは外部ルールで終了しません。 したがって、 Info



レベルのすべてのメッセージはtarget2



分類されtarget2









このルールのすべてのレシーバーが対応するチェーンに追加された後、メソッドは同じアルゴリズムに従って現在のルールのすべてのネストされたルールを再帰的に処理します。 これは、親ルールで有効になっているログレベルに関係なく発生します。







合計で、ロガーの構成の準備ができました。 ロギングの可能なレベルごとにフィルターを備えたレシーバーのチェーンが含まれています。







レシーバーチェーン







この構成がどのように使用されるかを見てみましょう。







ロガー構成の使用



簡単なことから始めましょう。 Logger



クラスには、 IsEnabled



メソッドと関連プロパティIsXXXEnabled



IsDebugEnabled



IsInfoEnabled



、...)があります。 彼らはどのように機能しますか? 実際、特定のレベルのロギングのレシーバーチェーンに少なくとも1つのリンクが含まれているかどうかを確認するだけです( こちらを参照)。 これは、フィルターがこれらのプロパティの値に影響を与えないことを意味します。







次に、メッセージを保護しようとするとどうなるかを説明します。 ご想像のとおり、ロガーはこのメッセージのログレベルのレシーバーチェーンを取得します。 その後、彼はこのチェーンのリンクを次々に処理し始めます。 ロガーは、リンクごとに、リンクで指定された受信者にメッセージを書き込むかどうか、およびその後のチェーンの処理を続行するかどうかを決定します。 これらの決定は、フィルターを使用して行われます。 NLogでフィルターがどのように機能するかを説明します。







フィルターの設定方法は次のとおりです。







 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <filters defaultAction='Log'> <when condition="contains('${message}','Common')" action="Ignore" /> </filters> </logger> </rules>
      
      





通常、フィルターにはブール条件が含まれます。 ここで、フィルターが各メッセージに対してtrue



またはfalse



を返すかどうかを決定できます。 しかし、これはそうではありません。 彼らの仕事の結果はFilterResult



型の値です。 フィルター条件がtrue



返す場合、フィルターの結果はaction



属性で指定された値になります(この例では、これはIgnore



)。 条件がfalse



返す場合、フィルターの結果はNeutral



ます。 これは、フィルターがメッセージの処理方法を決定したくないことを意味します。







ここで 、レシーバーチェーンの処理方法を確認できます 。 各レシーバーについて、 GetFilterResult



メソッドの対応するフィルターの結果がGetFilterResult



ます。 これは、非Neutral



を返した最初のフィルターの結果と等しくなります。 つまり、一部のフィルターがNeutral



以外の値を返す場合、後続のフィルターはすべて実行されません。







しかし、すべてのフィルターがNeutral



返すとどうなりますか? この場合、デフォルト値が使用されます。 この値は、ルールのfilters



エレメントのdefaultAction



属性を使用して設定されます。 defaultAction



のデフォルト値は何だと思いますか? これがNeutral



だと思うなら、あなたは正しい。 つまり、結果としてフィルターチェーン全体がNeutral



を返すことができます。 この場合、NLogはLog



を受け取るのと同じように動作します。 メッセージは受信者に書き込まれます( こちらを参照)。







IgnoreFinal



、フィルターがIgnore



またはIgnoreFinal



返す場合、メッセージはレシーバーに書き込まれません。 フィルターの結果がLog



またはLogFinal



場合、メッセージが記録されます。 しかし、 Ignore



IgnoreFinal



Log



またはLogFinal



何ですか? 簡単です。 IgnoreFinal



およびLogFinal



場合、 IgnoreFinal



はレシーバーのチェーンの処理を停止し、後続のリンクに含まれるレシーバーには何も書き込みません。







おわりに



NLogコードを分析することで、ルールとフィルターの仕組みを理解することができました。 この記事があなたにも役立つことを願っています。 頑張って








All Articles