2011-03-02 16 views
5

NLog, iletilerimi birkaç hedefe günlüğe kaydetmek için SplitGroup kullanmamı sağlıyor. Bu harikaNLog'da farklı düzenler aynı hedefe nasıl uygulanır?

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

fakat ben de için farklı düzenler kullanmak istiyorum: Tek seferde bir ortak, kullanıcıya özel ve tarih özgü günlükleri için günlüğüne her mesaj için bu özelliği kullanmak istiyorum Farklı şiddet dereceleri. Örneğin, errorLayout istisna bilgileri içerir ve [!] işaretleyici yüzden sonradan BareTail gibi günlük izleyiciler hataları vurgulamak olabilir ekler:

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

Bu kod Error hep istisnalar ile gelen varsayar ve Warning ler yok ama bu değil puan.

Bu sorun 'dir. Bu yapılandırma yanlış. Çalışmıyor, çünkü logger'un layout özniteliği yok. Yalnızca target için tanımlanmıştır.

Kullanılmakta olan düzen, hedeflerin kendileri tarafından beyan edilmek zorundadır, ancak farklı düzeyler için farklı düzenler belirtmenin hiçbir yolunu göremiyorum.

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

Bu sadece gözlerimi acıtıyor: Şimdilik

, sadece aynı dosya kümesi için dört farklı layout s olması aynı yapılandırma kodunu dört kez kopyalayıp yapıştırmak zorunda kaldı.
Bunu yapmak ve kopyalamaktan kaçınmanın daha iyi bir yolu var mı?

cevap

1

Emin değilim, ama muhtemelen çoğaltma ile sıkışmış olduğunu düşünüyorum. Aynı dosyada kullanılmak üzere 4 farklı düzen istiyor ve 3 farklı dosya istiyorsun. Bir hedef bir Düzen gerektirir. Dolayısıyla, yalnızca 1 dosyaya giriş yapmak isterseniz, her biri aynı dosyaya ve her biri kendi Düzenine sahip olan 4 Hedef tanımlamanız gerekir. NLog'un birden çok Layouts'u bir Hedefle ilişkilendirmek için daha uygun bir yolu olduğunu ve daha sonra kayıt mesajının içeriğine göre bir Layout'u seçtiğini düşünmüyorum.

Biçimlerinizle tam olarak neye ulaşmak istediğinize bağlı olarak, özel bir LayoutRenderer yazarak çoğaltmayı biraz azaltabilirsiniz. Örneğinizde, Debug düzeninin içinde "..." olduğunu, Bilgi [i], Warn'in [!] Ve Hata Uyarısının + istisnasının olduğunu gösterirsiniz. Mesajın seviyesine bağlı olarak özel işaretleyiciyi ekleyen bir LayoutRenderer yazabilirsiniz. Bu şekilde, Debug, Bilgi ve Tümünü bir Layout'a getirdiğinizde, Error kendi Layout'unu koruyacaktı.

özel LayoutRenderer için böyle

şey (nlog dayalı 1,0 yenileme, değil 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;  
    } 
    } 

Şimdi iki Düzenleri yapılandırabilirsiniz:

Örneğin

"normal" ve "hata ".gibi

şey:

<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}}" /> 

Muhtemelen bile istisnalar işlemek için özel bir LayoutRenderer oluşturabilir. Bir istisna yoksa, hiçbir şey üretmeyin. İstenirse, yeni satır, dolgu ve istisna dizesini birleştirin. Bir olmazdı çünkü

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

Çoğu zaman, ConditionalExceptionLayoutRenderer boş doğuracak: Bir "koşullu" istisna düzeni oluşturucusunu olsaydı

, o zaman bu gibi görünebilir sadece bir düzen olabilir istisna.

Bu yardımcı olur umarım.

+0

Yorumunuz için teşekkürler. Şimdilik asgari bağımlılıklara bağlı kalmak istiyorum ama sistemi yeniden kurduğumda, belki bunu uygulayacağım. –

8

Düzenlemede ne zaman bir koşulun kullanılması alternatif bir çözümdür.

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

Hatadan daha az bir şey olduğunda yalnızca istisna mesajını vermek istedim. Bir hata olduğunda tam yığın izini istedim.

+0

Bu kabul edilen cevap olmalı. Eğer OP'yi doğru bir şekilde anlarsam, bu hususu özellikle ele almak için şu soruya değinilmelidir: “Farklı seviyeler için farklı düzenler kullanmak istiyorum” ve bunun için uygun bir cevap olacaktır. – MattM