Question

I am using a custom ADONetAppender that defines the basic parameters, Date, Thread, Level, etc., but also uses a custom Parameter appender. It seems that on my Win 7 developmet machine, running SQL Server 2008 R2, it works fine, and the special parameter is added, which is tied to a bit column and is required (not null).

When running the service on a Win Server 2003 machine (tried one running SQL Server 2005, and another with 2008 R2), log4net fails to append the log to the DB, but my other appenders work. I know that log4net has internal debugging, but this is running a service, so I don't have access to the console. Is there compatability issues with different versions of windows, or some other suggested debugging action?

If I were to remove the extra parameter, the logs are written to the DB.

  <log4net>
    <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
      <param name="File" value="C:\Logs\Log.txt" />
      <param name="AppendToFile" value="true" />
      <param name="ImmediateFlush" value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="Header" value="[Header]&#xD;&#xA;" />
        <param name="Footer" value="[Footer]&#xD;&#xA;" />
        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
      </layout>
    </appender>
    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
      <bufferSize value="1"/>
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      <connectionString value="Data Source=localhost\SQLEXPRESS;Initial Catalog=mydb;Integrated Security=True"/>
      <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception],[IsCritical]) VALUES&#xD;&#xA;       (@log_date, @thread, @log_level, @logger, @message, 

@exception, @is_critical)"
                                                                       />
      <parameter>
        <parameterName value="@log_date"/>
        <dbType value="DateTime"/>
        <layout type="log4net.Layout.RawUtcTimeStampLayout"/>
      </parameter>
      <parameter>
        <parameterName value="@thread"/>
        <dbType value="String"/>
        <size value="32"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%t"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level"/>
        <dbType value="String"/>
        <size value="512"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%p"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger"/>
        <dbType value="String"/>
        <size value="512"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%c"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message"/>
        <dbType value="String"/>
        <size value="4000"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%m"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception"/>
        <dbType value="String"/>
        <size value="2000"/>
        <layout type="log4net.Layout.ExceptionLayout"/>
      </parameter>
      <parameter type="MyApp.Logging.IsCriticalAdoNetParameter">
        <parameterName value="@is_critical"/>
        <dbType value="Boolean"/>
        <size value="10"/>
        <layout type="log4net.Layout.PatternLayout" value=""/>
      </parameter>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="LogFileAppender" />
      <appender-ref ref="ADONetAppender"/>
    </root>
  </log4net>

Custom parameters:

   public class IsCriticalAdoNetParameter : AdoNetAppenderParameter
    {
        public override void FormatValue(IDbCommand command, LoggingEvent loggingEvent)
        {
            // Lookup the parameter
            IDbDataParameter param = (IDbDataParameter)command.Parameters[ParameterName];

            // extension method, returns bool.
            param.Value = loggingEvent.IsCritical();
        }
   }

Update, did some debugging with a small console app that has the same logging section. It seems to be blowing up on the column name. It seems to imply that the column doesn't exist, but it does. I wonder if it's an issue with converting the boolean to the actual SQL data type?

log4net: XmlHierarchyConfigurator: Setting Property [Layout] to object [log4net.
Layout.Layout2RawLayoutAdapter]
log4net: XmlHierarchyConfigurator: Setting Collection Property [AddParameter] to
 object [log4net.Appender.AdoNetAppenderParameter]
log4net: SystemInfo: Loaded type [MyApp.Logging.IsCriticalAdoNetPar
ameter] from assembly [MyApp, Version=2.0.0.2929, Culture=neutral,
PublicKeyToken=null] by searching loaded assemblies.
log4net: XmlHierarchyConfigurator: Setting Property [ParameterName] to String va
lue [@is_critical]
log4net: XmlHierarchyConfigurator: Setting Property [DbType] to DbType value [Bo
olean]
log4net: XmlHierarchyConfigurator: Setting Property [Size] to Int32 value [1]
log4net: XmlHierarchyConfigurator: Parameter [layout] specified subtype [log4net
.Layout.PatternLayout]
log4net: XmlHierarchyConfigurator: Performing additional conversion of value fro
m [PatternLayout] to [IRawLayout]
log4net: XmlHierarchyConfigurator: Setting Property [Layout] to Layout2RawLayout
Adapter value [log4net.Layout.Layout2RawLayoutAdapter]
log4net: XmlHierarchyConfigurator: Setting Collection Property [AddParameter] to
 object [MyApp.Logging.IsCriticalAdoNetParameter]
log4net: XmlHierarchyConfigurator: Created Appender [ADONetAppender]
log4net: XmlHierarchyConfigurator: Adding appender named [ADONetAppender] to log
ger [root].
log4net: XmlHierarchyConfigurator: Hierarchy Threshold []
log4net:ERROR [AdoNetAppender] Exception while writing to database
System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'IsCritical
'.
Statement(s) could not be prepared.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolea
n breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception
, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
Was it helpful?

Solution

First, I changed my custom parameter to be size of 1 since it's a boolean (bit). While this didn't fix the problem, it's a more correct configuration.

  <parameter type="MyApp.Logging.IsCriticalAdoNetParameter">
    <parameterName value="@is_critical"/>
    <dbType value="Boolean"/>
    <size value="1"/>
    <layout type="log4net.Layout.PatternLayout" value=""/>
  </parameter>

Finally, it seemed that through some tracing, the custom parameter was not a loaded assembly, so I explicitly constructed the parameter in the bootstrapping phase, after I ran the XML Configurator. I think log4net was struggling to find the Appender using reflection since it wasn't a loaded assembly yet.

    XmlConfigurator.Configure();
    // this ensure the ado net appender is loaded.
    IsCriticalAdoNetParameter adoNetParameter = new IsCriticalAdoNetParameter();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top