2011-03-02 6 views
5

NLog를 사용하면 SplitGroup을 사용하여 내 메시지를 여러 대상에 기록 할 수 있습니다. 이것은 대단한NLog에서 동일한 대상에 다른 레이아웃을 적용하는 방법은 무엇입니까?

<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의 항상 예외와 함께 가정 Warning들하지 않습니다하지만 그건 아니다 포인트.

문제는 입니다.이 구성은 잘못된입니다. logger에는 layout 속성이 없으므로 작동하지 않습니다. target에 대해서만 정의됩니다.

사용중인 레이아웃은 대상 자체에 의해 선언되어야하지만 다른 심각도 수준에 대해 다른 레이아웃을 지정하는 방법은 없습니다.

<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 개 개의 다른 layout의이 동일한 구성 코드를 네 번 복사 - 붙여 넣기했다.
이 작업을 수행하고 중복을 피하는 더 좋은 방법이 있습니까?

답변

1

확실하지 않지만 아마도 복제본에 집착하고 있다고 생각합니다. 같은 파일에 4 가지 다른 레이아웃을 사용하고 3 가지 다른 파일을 원한다. 하나의 대상에는 하나의 레이아웃이 필요합니다. 따라서 하나의 파일에만 기록하려면 4 개의 대상을 정의해야합니다. 각 대상은 동일한 파일을 가리키고 각각은 고유 한 레이아웃을가집니다. NLog에는 여러 레이아웃을 대상과 연관시킨 다음 로깅 메시지의 내용을 기반으로 하나의 레이아웃을 선택하는보다 편리한 방법이 있다고 생각하지 않습니다.

포맷으로 얻고 자하는 것이 무엇인지에 따라 사용자 정의 LayoutRenderer를 작성하여 복제를 다소 줄일 수 있습니다. 예를 들어, 디버그 레이아웃에 "..."이 있고 Info에 [i], 경고에 [!], 오류에 경고 + 예외가 있음을 보여줍니다. 메시지의 레벨에 따라 특수 마커를 추가하는 LayoutRenderer을 작성할 수 있습니다. 그렇게하면 Debug, Info, Warn 모두를 하나의 레이아웃으로 만들고 오류는 자체 Layout을 유지합니다.

사용자 정의 LayoutRenderer이 같은

뭔가 (NLog에 따라 1.0 새로 고침하지 2.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;  
    } 
    } 

지금 두 개의 레이아웃을 구성 할 수 있습니다 :

예를 들어

"정상"및 "오류 ".같은

뭔가 :

<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를 만들 수 있습니다. 예외가 없으면 아무 것도 출력하지 마십시오. 예외 인 경우, 개행 문자, 패딩 및 예외 문자열을 결합합니다. 이되지 않을 것 때문에

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

대부분의 시간, ConditionalExceptionLayoutRenderer는 null를 얻을 것입니다 : 당신이 "조건"예외 레이아웃 렌더러를 가지고 있다면

, 당신은 다음과 같을 수 하나의 레이아웃을 가질 수있다 예외.

희망이 도움이됩니다.

+0

의견을 보내 주셔서 감사합니다. 지금은 최소한의 의존성을 고수하고 싶지만, 시스템을 재 설계 할 때는 아마도 이것을 구현할 것입니다. –

8

다른 해결책은 레이아웃에서 조건을 사용하는 것입니다.

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

오류가 발생하면 예외 메시지를 보내고 싶었습니다. 오류가 발생했을 때 전체 스택 추적을 원했습니다.

+0

이것은 허용 된 대답이어야합니다. OP를 올바르게 이해한다면이 질문을 다음과 같이 구체적으로 표현해야합니다. "각기 다른 수준의 레이아웃에 서로 다른 레이아웃을 사용하고 싶습니다."그러면 올바른 대답이됩니다. – MattM

관련 문제