2010-06-08 26 views
5

Estoy tratando de implementar log4net logger/logmanager personalizado para poder agregar un nuevo nivel. También quiero tener el esquema de la tabla de objetivos (estoy usando AdoNetAppender y SQL Server 2008) para tener algunos campos opcionales; por ejemplo, el nivel que estoy agregando se usa para rastrear el uso, y uno de los campos necesita ser una Duración (para decirnos cuánto tiempo tomó algo). Sin embargo, otros niveles (INFO, DEPURAR, FATAL, etc.) no tendrán ningún valor para la Duración. Por lo tanto, debo poder insertar en la tabla no todos los campos con valores, preferiblemente sin tener que volver a implementar todos los niveles estándar de registro para pasar un valor nulo para los campos irrelevantes. Idealmente, log4net pasa automáticamente NULL para valores de propiedad que no puede encontrar para un evento de registro particular.log4net propiedades personalizadas que no funcionan

El código en mi registrador personalizado es el siguiente:

public void Usage(TimeSpan? duration, DateTime? startTime, DateTime? endTime, string message) 
    { 
     if (IsUsageEnabled) 
     { 
      LoggingEvent loggingEvent = new LoggingEvent(GetType(), Logger.Repository, Logger.Name, _currentUsageLevel, 
       message, null); 
      if (startTime.HasValue) 
      { 
       loggingEvent.Properties["StartTime"] = startTime.Value; 
      } 
      else 
      { 
       loggingEvent.Properties["StartTime"] = DBNull.Value; 
      } 

      if (endTime.HasValue) 
      { 
       loggingEvent.Properties["EndTime"] = endTime.Value; 
      } 
      else 
      { 
       loggingEvent.Properties["EndTime"] = DBNull.Value; 
      } 

      if (duration.HasValue) 
      { 
       loggingEvent.Properties["Duration"] = duration.Value.TotalMilliseconds; 
      } 
      else 
      { 
       loggingEvent.Properties["Duration"] = DBNull.Value; 
      } 

      Logger.Log(loggingEvent); 
     } 
    } 

(se han añadido las asignaciones a DBNull.Value con la esperanza de que eso ayudaría a los nulos de paso log4net cuando no se pasa el valor, pero espero que se puede quitar).

La configuración appender es el siguiente:

<appender name="SQLAppender" type="log4net.Appender.AdoNetAppender"> 
    <bufferSize value="1" /> 
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    <connectionString value="my connection string (which actually gets replaced at runtime with a connection string retrieved from a config database)" /> 
    <commandText value="INSERT INTO MyTable ([Date],[Thread],[Level],[Logger],[Message],[Exception], [Login], [StartTime], [EndTime], [Duration]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, @login, @start_time, @end_time, @duration)" /> 
    <parameter> 
    <parameterName value="@log_date" /> 
    <dbType value="DateTime" /> 
    <layout type="log4net.Layout.RawTimeStampLayout" /> 
    </parameter> 
    <parameter> 
    <parameterName value="@thread" /> 
    <dbType value="String" /> 
    <size value="255" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%thread" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@log_level" /> 
    <dbType value="String" /> 
    <size value="50" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%level" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@logger" /> 
    <dbType value="String" /> 
    <size value="255" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%logger" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@message" /> 
    <dbType value="String" /> 
    <size value="4000" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%message" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@exception" /> 
    <dbType value="String" /> 
    <size value="4000" /> 
    <layout type="log4net.Layout.ExceptionLayout" /> 
    </parameter> 
    <parameter> 
    <parameterName value="@login" /> 
    <dbType value="String" /> 
    <size value="255" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%property{CurrentLogin}" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@start_time" /> 
    <dbType value="DateTime" /> 
    <layout type="log4net.Layout.PatternLayout" 
     value="%property{StartTime}" /> 
    </parameter> 
    <parameter> 
    <parameterName value="@end_time" /> 
    <dbType value="DateTime" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%property{EndTime}" /> 
    </layout> 
    </parameter><parameter> 
    <parameterName value="@duration" /> 
    <dbType value="Double" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%property{Duration}" /> 
    </layout> 
    </parameter> 
</appender> 

Cuando intento acceder algo con mi nivel personalizado, sólo funciona si paso en la duración, starttime y tiempo del fin. Para cualquier otra cosa, incluidos los niveles predeterminados, parece fallar silenciosamente, sin pistas en la ventana de salida (aunque el registro con niveles predeterminados arroja excepciones que dicen que no puede convertir String en DateTime o Double).

¿Alguna razón para que alguien pueda ver por qué esto podría fallar silenciosamente de esta manera?

Respuesta

7

Finalmente lo descubrí, después de rastrear a través de alguna fuente de log4net. El problema era que estaba usando un PatternLayout para representar los parámetros personalizados. Este diseño fuerza null a la cadena "(null)", lo que causa problemas si intenta insertarlo, por ejemplo, en un campo que admite valores de nulo datetime en la tabla. La solución es simple: en lugar de usar el diseño de PatternLayout, use log4net.Layout.RawPropertyLayout. Esto pasará una propiedad nula como null, que es lo que desea.

+0

tuvo que usarlo así: new RawPropertyLayout {Key = propertyName} – xhafan

Cuestiones relacionadas