8

NLogを使用SplitGroupすると、メッセージを複数のターゲットに記録するために使用できます。この機能を使用して、各メッセージを共通のユーザー固有および日付固有のログに一度に記録したいと思います。

<variable name="commonLog" value="${logDir}\Common.log" />
<variable name="username" value="${identity:fSNormalize=true:authType=false:isAuthenticated=false}" />
<variable name="userLog" value="${logDir}\ByUser\${username}.log" />
<variable name="dateLog" value="${logDir}\ByDate\${shortdate}.log" />

<target name="logFiles" xsi:type="SplitGroup">
  <target xsi:type="File" fileName="${commonLog}" layout="${myLayout}" />
  <target xsi:type="File" fileName="${userLog}" layout="${myLayout}" />
  <target xsi:type="File" fileName="${dateLog}" layout="${myLayout}" />
</target>

これは素晴らしいことですが、重大度のレベルごとに異なるレイアウトを使用したいと思います。たとえばerrorLayout、例外情報を含めて[!]マーカーを挿入すると、後でBareTailなどのログビューアでエラーを強調表示できるようになります。

<variable name="stamp" value="${date} ${username} ${logger}" />

<variable name="debugLayout" value="${stamp} ... ${message}" />
<variable name="infoLayout" value="${stamp} [i] ${message}" /> 
<variable name="warnLayout" value="${stamp} [!] ${message}" />
<variable name="errorLayout"
   value="${warnLayout}${newline}${pad:padding=10:inner=${exception:format=ToString}}" />

<!-- logFiles target -->

<rules>
  <logger name="*" level="Debug" writeTo="logFiles" layout="debugLayout"  />
  <logger name="*" level="Info" writeTo="logFiles" layout="infoLayout" />
  <logger name="*" level="Warn" writeTo="logFiles" layout="warnLayout" />
  <logger name="*" level="Error" writeTo="logFiles" layout="errorLayout" />
</rules>

Errorこのコードは、sには常に例外があり、例外がないことを前提とWarningしていますが、それは重要ではありません。

問題は、この構成が間違っていることです。属性がないためlogger動作しません。layoutのみに定義されてtargetいます。

使用されているレイアウトは、ターゲット自体が宣言する必要がありますが、重大度レベルごとに異なるレイアウトを指定する手段がありません。

layout今のところ、同じファイルセットに対して4つの異なるを作成するために、同じ構成コードを4回コピーアンドペーストする必要がありました。

<targets>
  <target name="logFilesDebug" xsi:type="SplitGroup">
    <target xsi:type="File" fileName="${commonLog}" layout="${debugLayout}" />
    <target xsi:type="File" fileName="${userLog}" layout="${debugLayout}" />
    <target xsi:type="File" fileName="${dateLog}" layout="${debugLayout}" />
  </target>

  <target name="logFilesInfo" xsi:type="SplitGroup">
    <target xsi:type="File" fileName="${commonLog}" layout="${infoLayout}" />
    <target xsi:type="File" fileName="${userLog}" layout="${infoLayout}" />
    <target xsi:type="File" fileName="${dateLog}" layout="${infoLayout}" />
  </target>

  <target name="logFilesWarn" xsi:type="SplitGroup">
    <target xsi:type="File" fileName="${commonLog}" layout="${warnLayout}" />
    <target xsi:type="File" fileName="${userLog}" layout="${warnLayout}" />
    <target xsi:type="File" fileName="${dateLog}" layout="${warnLayout}" />
  </target>

  <target name="logFilesError" xsi:type="SplitGroup">
    <target xsi:type="File" fileName="${commonLog}" layout="${errorLayout}" />
    <target xsi:type="File" fileName="${userLog}" layout="${errorLayout}" />
    <target xsi:type="File" fileName="${dateLog}" layout="${errorLayout}" />
  </target>
</targets>

<rules>
  <logger name="*" level="Debug" writeTo="logFilesDebug"  />
  <logger name="*" level="Info" writeTo="logFilesInfo" />
  <logger name="*" level="Warn" writeTo="logFilesWarn" />
  <logger name="*" level="Error" writeTo="logFilesError" />
</rules>

これは私の目を痛めるだけです。
これを行い、重複を避けるためのより良い方法はありますか?

4

2 に答える 2

16

別の解決策は、レイアウトでwhen条件を使用することです。

target.Layout = "${longdate}|[${level}]|${logger}|${message}${onexception:inner=|${exception}${when:when=(level > LogLevel.Warn):inner=|[!] ${exception:format=ToString:innerFormat=Message:maxInnerExceptionLevel=5} }}"

エラー以外の場合は、例外メッセージを提供したかっただけです。エラーが発生したときは、フルスタックトレースが必要でした。

于 2012-11-23T01:35:40.230 に答える
1

よくわかりませんが、おそらく重複に悩まされていると思います。同じファイルで4つの異なるレイアウトを使用し、3つの異なるファイルを使用する必要があります。1つのターゲットには1つのレイアウトが必要です。したがって、1つのファイルにのみログを記録する場合でも、それぞれが同じファイルを指し、それぞれが独自のレイアウトを持つ4つのターゲットを定義する必要があります。NLogには、複数のレイアウトをターゲットに関連付けて、ログメッセージの内容に基づいて1つのレイアウトを選択するより便利な方法があるとは思いません。

フォーマットで何を達成したいかによっては、カスタムLayoutRendererを作成することで、重複をいくらか減らすことができる場合があります。この例では、デバッグレイアウトに「...」が含まれ、情報に[i]が含まれ、警告に[!]が含まれ、エラーに警告+例外が含まれていることを示しています。メッセージのレベルに応じて、特別なマーカーを追加するLayoutRendererを作成できます。そうすれば、デバッグ、情報、警告をすべて1つのレイアウトにまとめ、エラーは独自のレイアウトを保持します。

例えば:

カスタムLayoutRendererの場合は次のようになります(2.0ではなくNLog 1.0の更新に基づく):

  [LayoutRenderer("LevelMarkerLayoutRenderer")]   
  class LevelMarkerLayoutRenderer : LayoutRenderer   
  {     
    int estimatedSize = 3;      
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {       
      string marker;
      switch (logEvent.Level)
      {
        case Debug:
          marker = "...";
          break;
        case Info:
          marker = "[i]";
          break;
        case Warn:
          marker = "[!]";
          break;
        case Error:
          marker = "[!]";
          break;
        case Fatal:
          marker = "[!]";
          break;
        default:
          marker = "?";
      }

      builder.Append(marker);     
    }      

    protected override int GetEstimatedBufferSize(LogEventInfo logEvent)     
    {       
      return estimatedSize;     
    }
  } 

これで、「通常」と「エラー」の2つのレイアウトを構成できます。

何かのようなもの:

<variable name="stamp" value="${date} ${username} ${logger}" />

<variable name="normal" value="${stamp} ${LevelMarkerLayoutRenderer} ${message}" />
<variable name="error"
   value="${warnLayout}${newline}${pad:padding=10:inner=${exception:format=ToString}}" />

おそらく、例外を処理するためのカスタムLayoutRendererを作成することもできます。例外がなければ、何も出力しないでください。例外の場合は、改行、パディング、および例外文字列を連結します。

「条件付き」例外レイアウトレンダラーがある場合は、次のようなレイアウトを1つだけ持つことができます。

<variable name="normal" value="${stamp} ${LevelMarkerLayoutRenderer} ${message} ${ConditionalExceptionLayoutRenderer}" />

ほとんどの場合、ConditionalExceptionLayoutRendererは例外がないため、nullを生成します。

お役に立てれば。

于 2011-03-02T21:47:34.773 に答える