21

I tried to configure log4net for logging everything to the console output. I have a config file named Log4Net.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="INFO" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
</configuration>

and I have my main class (just a testing case)

namespace TestLog4Net {
    class Program {
        private static readonly ILog log = LogManager.GetLogger(typeof(Program));

        static void Main(string[] args) {
            log.Info("Info");
            log.Error("Error");
            Console.ReadKey();
        }
    }
}

I added these lines to the AssemblyInfo.cs

[assembly: log4net.Config.XmlConfigurator(
ConfigFile = "Log4Net.config", Watch = true)]

But now nothing is logged, can someone explain this?

RBT
  • 24,161
  • 21
  • 159
  • 240
Sebastian Müller
  • 5,471
  • 13
  • 51
  • 79
  • I am getting exactly same problem. I have similar implementation and still i am not able to fix the problem. Can you pls help me fix it ? – Karthikeyan Jul 14 '11 at 05:17
  • 2
    Ensure the log4net.config file is marked as “Copy To Output” -> “Copy Always” in Properties. – Amit Jan 19 '14 at 21:54
  • 1
    Related post - [Log4net xml output](https://stackoverflow.com/q/1147103/465053) – RBT Sep 15 '21 at 05:33

3 Answers3

22

When you have log4net config in a separate config file you should not include the configuration and configSections elements. log4net should be the top level element after the xml declartion.

Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
21

Try this custom configuration through code. Worked for me and tested in multiple apps..

string logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "\\Config\\Log4Net.config");
    FileInfo finfo = new FileInfo(logFilePath);
   log4net.Config.XmlConfigurator.ConfigureAndWatch(finfo); 

I understand it's a very late reply. But will be useful for some right.

nithinmohantk
  • 459
  • 4
  • 11
4

I believe the file that you've mentioned in your post is the content of App.config file instead. App.config is the default configuration file for a variety of C# project templates like WinForm application, Console application, etc. So you should consider naming it as App.config in place of Log4Net.config.

In order to have a full fledged understanding, let us go through three possible ways of configuring log4net:

  1. If we want to use our application's App.config file to hold the settings of log4net, then we'll have to add the below mentioned declaration in AssemlyInfo.cs file to below line:

    [assembly: log4net.Config.XmlConfigurator(Watch = true)]
    

    App.config will hold the log4net settings like this:

     <?xml version="1.0" encoding="utf-8" ?>
     <configuration>
       <configSections>
         <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
       </configSections>
       <log4net>
         <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
           <layout type="log4net.Layout.PatternLayout">
             <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
           </layout>
         </appender>
         <root>
           <level value="INFO" />
           <appender-ref ref="ConsoleAppender" />
         </root>
       </log4net>
     </configuration>
    
  2. In some scenario, we might want to use a dedicated file for holding settings of log4net. We can name it e.g. log4net.config or log4net.xml. While creating such a dedicated config file, we need to ensure that log4net is the root tag of the config file (Refer file-snippet):

    <log4net>
         <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
           <layout type="log4net.Layout.PatternLayout">
             <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
           </layout>
         </appender>
         <root>
           <level value="INFO" />
           <appender-ref ref="ConsoleAppender" />
         </root>
    </log4net>
    

    In this case, we require following declaration in AssemblyInfo.cs file. Same declaration has been mentioned in the OP's question also:

    [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
    
  3. Now the final use-case. Let's say we're having a custom xml file of our own e.g. myCustomSettings.xml which contains log4net setting. In this case log4net tag is present in a custom config file but it is not the root tag of that file (Refer file-snippet)

    <MyCustomSetting>
      <mySection1></mySection1>
      <mySection2></mySection2>
      <log4net>
         <root>
             <level value="ALL" />
             <appender-ref ref="file" />
             <appender-ref ref="console" />
         </root>
         <appender name="console" type="log4net.Appender.ConsoleAppender">
           <layout type="log4net.Layout.PatternLayout">
             <conversionPattern value="%date %level  - %message%newline" />
           </layout>
           <threshold value="Info" />
         </appender>
         <appender name="file" type="log4net.Appender.RollingFileAppender">
            <file value="${PROGRAMDATA}\MyProduct\myLogs.log" />
            <appendToFile value="true" />
            <rollingStyle value="Size" />
            <maxSizeRollBackups value="5" />
            <maximumFileSize value="10MB" />
            <staticLogFileName value="true" />
            <threshold value="Debug" />
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
            </layout>
         </appender>
       </log4net>
     </MyCustomSetting>
    

    In such a case we'll have to configure log4net through C# code at run-time (Refer code-snippet).

     using System.Xml;
    
     var configFilePath = "myCustomSettings.xml";
     var log4netConfig = new XmlDocument();
     log4netConfig.Load(File.OpenRead(configFilePath));
    
     var repo = LogManager.CreateRepository(Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
    
     var log4NetXml = log4netConfig["MyCustomSetting"]["log4net"];
     log4net.Config.XmlConfigurator.Configure(repo, log4NetXml);
    

    In this case we don't require the declarative configuration in AssemblyInfo.cs file. So please make sure that you've removed it from there:

     //TODO: Remove it
     [assembly: log4net.Config.XmlConfigurator(Watch = true)]
    
RBT
  • 24,161
  • 21
  • 159
  • 240
  • Excellent answer! I'm well aware that this question is old, but it seems that after well over a decade, it's still a nightmare to properly configure log4net. I'm aware that this question is ancient, and that the OP has probably left SO æons ago, but your answer ought to be promoted to be the correct solution. – Gwyneth Llewelyn Apr 27 '22 at 01:11