Log4Net with AdoNetAppender - nothing happens

29,461

Solution 1

You can debug log4net by hooking into the log4net DebugAppender:

Add a log4net app setting in your app.config file:

<appSettings>
  <!-- log4net configuration when running in debug mode. -->    
  <add key="log4net.Internal.Debug" value="true" />   
</appSettings>

Add a debug appender in the log4net config:

<appender name="DebugAppender" type="log4net.Appender.DebugAppender">
  <immediateFlush value="true" />
  <layout type="log4net.Layout.SimpleLayout" />
</appender>

Add the appender to the log4net config root:

<root>
  <level value="ALL" />
  <appender-ref ref="AdoNetAppender" />
  <appender-ref ref="DebugAppender" />
</root>

When you run your application, look in the output window of Visual Studio and you should see all the internal logging for log4net. If not, then the log4net config file is never loading.

Edit

If you can use a connection string from your app.config file, then remove the connection string from the log4net AdoNetAppender and just call the connection string by name:

<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
  <bufferSize value="1" />
  <!-- note: you can use the 4.0 assembly -->
  <connectionType value="System.Data.SqlClient.SqlConnection,
              System.Data, 
              Version=4.0.0.0, 
              Culture=neutral, 
              PublicKeyToken=b77a5c561934e089" />
  <!-- This will retrieve a connection string by name from the app.config -->
  <connectionStringName value="ConnectionStringNameFromAppConfig" />
  <!-- snip -->
</appender>

Solution 2

Here are some things that I tried that worked out for me...

  • I wasn't seeing anything because my <appender-ref ref="AdoNetAppender" /> didn't properly reference my <appender name="AdoNetAppender" ... /> in the Web.config. The 'AdoNetAppender' names need to match.

  • Added <bufferSize value="1" /> to the <appender name="AdoNetAppender" /> section of the Web.config

  • I created a user account with a password on the SQL server instead of using windows authentication. Granted user access to perform selects and inserts on the table

  • In Global.asax.cs I initialize log4net using log4net.Config.XmlConfigurator.Configure();

  • In my C# code I instantiate a new adoAppender object and call logger.Info("save to db");

The documentation on Apache's website is helpful as well ... http://logging.apache.org/log4net/release/config-examples.html#MS%20SQL%20Server

Hope that saves somebody some time and frustration. Thanks!

Share:
29,461

Related videos on Youtube

dknaack
Author by

dknaack

Updated on July 17, 2022

Comments

  • dknaack
    dknaack almost 2 years

    Description

    I have a config file as a resource in my assembly and want to change the ConnectionString programmatically in my application.

    I load the configuration using log4net.Config.XmlConfigurator.Configure.

    I have some breakpoints and see that the configuration is loaded successfuly and the connectionstring is Data Source=localhost\SQLExpress;Initial Catalog=Log;Integrated Security=SSPI; (local SQLExpress).

    Problem

    Nothing happens, no exception and no log entry. Any ideas.

    using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("MyNamespace.Properties.log4net.config"))
    { 
        // stream is NOT null
        log4net.Config.XmlConfigurator.Configure(stream);
    }
    
    Hierarchy hier = LogManager.GetRepository() as Hierarchy;
    
    if (hier != null)
    {
        //get ADONetAppender
        var adoAppender = (AdoNetAppender)hier.GetAppenders().Where(appender => appender.Name.Equals("AdoNetAppender", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
    
        if (adoAppender != null)
        {
            // update connectionstring
            adoAppender.ConnectionString = configuration.GetConnectionString(ConnectionStringNames.Log).ConnectionString;
            //refresh settings of appender
            adoAppender.ActivateOptions(); 
        }
    }
    
    ILog logger = LogManager.GetLogger("MyProject"); 
    logger.Warn("Test");
    

    content of the log4net.config file

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
      </configSections>
    
      <log4net>
        <appender name="AdoNetAppender" 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="[we will set this automatically at runtime]" />
          <commandText value="INSERT INTO Log ([Date],[Level],[Logger],[Message],[Exception])
      VALUES (@log_date, @log_level, @logger, @message, @exception)" />
          <parameter>
            <parameterName value="@log_date" />
            <dbType value="DateTime" />
            <layout type="log4net.Layout.RawTimeStampLayout" />
          </parameter>
          <parameter>
            <parameterName value="@log_level" />
            <dbType value="String" />
            <size value="50" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%p" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@logger" />
            <dbType value="String" />
            <size value="255" />
            <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>
        </appender>
    
        <root>
          <level value="ALL" />
          <appender-ref ref="AdoNetAppender" />
        </root>
      </log4net>
    </configuration>
    
    • Kirk Woll
      Kirk Woll almost 12 years
      Total side-note, but isn't it a lot better for the config file to exist side-by-side with your assembly, rather than being baked in? After all, the main reason it's in a config file (and not defined in C# code) is so you can tweak it without recompiling your app.
    • dknaack
      dknaack almost 12 years
      In general, yes. But in my situation, i need it from a resource.
  • dknaack
    dknaack almost 12 years
    Thank you, the exception is that log4net cant connect the database with the connectionstring "[we will set this automatically at runtime]". Thats ok, i change the connectionstring in code. Any other idea ?
  • Metro Smurf
    Metro Smurf almost 12 years
    Are you using the same connection string that is defined in the app.config file? And is the actual error from the output window: "log4net cant connect the database with the connectionstring '[we will set this automatically at runtime]'"?
  • dknaack
    dknaack almost 12 years
    this message comes before i call the first Warn message.
  • Metro Smurf
    Metro Smurf almost 12 years
    You say that you change the connection string in code/runtime, but the log4net debugger is clearly stating that it can not connect to the database with a connection string of "we will set this automatically at runtime". Are there any errors after the first Warn message?
  • dknaack
    dknaack almost 12 years
    The message comes on log4net.Config.XmlConfigurator.Configure, after this no other messages comes.
  • Metro Smurf
    Metro Smurf almost 12 years
    See my edit for using a connection string by name from the app.config. If that is not an option, then try hard-coding the connection string in the log4net config file to verify the connection is working correctly, if it is, then there is something wrong with how the connection string is being updated in code.
  • Shawn J. Molloy
    Shawn J. Molloy almost 11 years
    Highly useful answer; excellent instructions, and works great.
  • Tony
    Tony over 10 years
    I have tried a hand full of other debugging steps others have mentioned, this is the only one that allowed me to see what i needed to see :) forgot to set me ID column as an Identity :( there went my morning lol. Thanks!!
  • Whatever Man
    Whatever Man almost 9 years
    Your second point (buffer size) was the key for me. My bufferSize was 100, and so I was not seeing any output for a few minutes and assumed it was not working. Thanks.
  • Johnie Karr
    Johnie Karr over 8 years
    Plus 1 for the DebugAppender
  • Alexander Derck
    Alexander Derck over 8 years
    Buffer size did it for me too. The documentation of config files by log4net really lacks...
  • techvice
    techvice almost 8 years
    Here is the documentation for BufferSize.
  • Maximiliano Rios
    Maximiliano Rios almost 8 years
    I tried everything until I found the buffer size was preventing the database write for a long time. Thanks for pointing out this
  • Moi Hawk
    Moi Hawk about 5 years
    I've done all of this and I'm not getting any feedback from the debugAppender. I am calling Log.error("write this error"); and that writes to the output window but i still get nothing in the sql table. any ideas?