2011-03-02 15 views
5

NLog me permite usar SplitGroup para registrar mis mensajes en varios destinos. Me gustaría utilizar esta función para registro de cada mensaje a una, registros específicos del usuario y la fecha específica comunes a la vez:¿Cómo aplicar diferentes diseños al mismo objetivo en 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> 

Esto es muy bueno, pero también quiero utilizar diferentes diseños para diferentes niveles de severidad. Por ejemplo, errorLayout incluiría información de excepción e insertar [!] marcador por lo que más tarde podría poner de relieve los errores en los espectadores de registro como 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> 

Este código asume Error s siempre vienen con excepciones y Warning s no lo hacen, pero ese no es el punto.

El problema es esta configuración es incorrecta. No funcionará porque logger no tiene el atributo layout. Está definido solo para target.

El diseño que se está utilizando debe ser declarado por los propios objetivos, pero no veo ninguna forma de especificar diseños diferentes para diferentes niveles de gravedad.

Por ahora, tuve que copiar y pegar el mismo código de configuración cuatro veces sólo para tener cuatro layout s diferentes para un mismo conjunto de archivos:

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

Esto sólo duelen los ojos.
¿Hay alguna manera mejor de hacer esto y evitar la duplicación?

Respuesta

1

No estoy seguro, pero creo que probablemente esté atascado con la duplicación. Desea que se utilicen 4 diseños diferentes en el mismo archivo y desea 3 archivos diferentes. Un objetivo requiere un diseño. Por lo tanto, si solo desea iniciar sesión en 1 archivo, aún deberá definir 4 objetivos, cada uno apuntando al mismo archivo y cada uno con su propio diseño. No creo que NLog tenga una manera más conveniente de asociar múltiples diseños con un objetivo y luego elegir un diseño basado en el contenido del mensaje de registro.

Dependiendo exactamente de lo que desee lograr con sus formatos, es posible que pueda reducir algo la duplicación escribiendo un LayoutRenderer personalizado. En su ejemplo, usted muestra que el diseño de Debug tiene "...", Info tiene [i], Warn tiene [!] Y Error tiene Warn + excepción. Podría escribir un LayoutRenderer que agregue el marcador especial, dependiendo de cuál sea el nivel del mensaje. De esta forma, usted eliminaría Debug, Info y Warn all en un Layout and Error y conservaría su propio Layout.

Por ejemplo:

Algo como esto para un LayoutRenderer personalizado (1.0 basado en Nlog de refresco, no 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;  
    } 
    } 

Ahora se podría configurar dos diseños: "normal", y "el error ".

Algo así como:

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

que probablemente podría incluso crear un LayoutRenderer personalizada para manejar excepciones. Si no es una excepción, no generes nada. Si es una excepción, concatenar nueva línea, relleno y la cadena de excepción.

Si tuviera un "condicional" procesador de diseño excepción, entonces usted podría tener sólo un diseño que podría tener este aspecto:

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

mayoría de las veces, ConditionalExceptionLayoutRenderer cedería nula porque no habría una excepción.

Espero que esto ayude.

+0

Gracias por su comentario. Por ahora quiero mantener dependencias mínimas, pero cuando reinvente el sistema, quizás lo implemente. –

8

Una solución alternativa es utilizar la condición when en el diseño.

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

Yo sólo quería dar el mensaje de excepción, cuando nada menos que de error. Cuando había un error, quería un seguimiento completo de la pila.

+0

Esta debería ser la respuesta aceptada. Si entiendo el OP correctamente, la pregunta debe reformularse para abordar esto específicamente: "También quiero usar diferentes diseños para diferentes niveles de gravedad", y esta sería la respuesta adecuada para eso. – MattM

Cuestiones relacionadas