2010-06-08 21 views
5

Sto cercando di implementare un logger log4net personalizzato/logmanager in modo da poter aggiungere un nuovo livello. Voglio anche avere lo schema della tabella di destinazione (sto usando un AdoNetAppender e SQL Server 2008) per avere alcuni campi opzionali; per esempio, il livello che sto aggiungendo è usato per tracciare l'utilizzo, e uno dei campi deve essere una Durata (per dirci quanto tempo è durato qualcosa). Tuttavia, altri livelli (INFO, DEBUG, FATAL, ecc.) Non avranno alcun valore per la Durata. Quindi ho bisogno di essere in grado di inserire nella tabella con non tutti i campi con valori - preferibilmente senza dover reimplementare tutti i livelli standard di registrazione per passare un valore nullo per i campi irrilevanti. Idealmente, log4net passerebbe automaticamente NULL per i valori di proprietà che non può trovare per un particolare evento di registrazione.Proprietà personalizzate log4net non funzionanti

Il codice nel mio logger personalizzato è la seguente:

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); 
     } 
    } 

(le assegnazioni a DBNull.Value sono state aggiunte nella speranza che che avrebbe aiutato i null passa log4net quando il valore non è stata approvata, ma spero che può essere rimosso).

La configurazione appender è la seguente:

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

Quando provo ad accedere qualcosa con la mia livello personalizzato, funziona solo se mi passate nella durata, starttime e endtime. Per qualsiasi altra cosa - inclusi i livelli predefiniti - sembra fallire silenziosamente, senza indizi nella finestra di output (sebbene l'accesso ai livelli predefiniti genera eccezioni che dicono che non può convertire String in DateTime o Double).

Qualche ragione per cui chiunque può capire perché questo fallirebbe silenziosamente in questo modo?

risposta

7

Alla fine l'ho capito, dopo aver tracciato qualche sorgente log4net. Il problema era che stavo usando un PatternLayout per il rendering dei parametri personalizzati. Questo layout costringe null alla stringa "(null)", che causa problemi se si sta tentando di inserirlo in, diciamo, un campo n. datetime nella tabella. La soluzione è semplice: invece di usare il layout PatternLayout, usa log4net.Layout.RawPropertyLayout. Questo passerà una proprietà null come null, che è quello che vuoi.

+0

ha dovuto utilizzarlo in questo modo: new RawPropertyLayout {Key = propertyName} – xhafan

Problemi correlati