94

We are using log4net and want to specify it's configuration in an external config file (as we have done with other sections). To do this we have changed the log4net section in the App.config to:

...
<section name="log4net" 
     type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
...
<log4net configSource="Log.config" />
...

And in the Log.Config file (same directory as the App.config) we have:

<log4net>
  <appender name="General" type="log4net.Appender.FileAppender">
    <file value="myapp.log" />
    <layout type="log4net.Layout.SimpleLayout" />
  </appender>
  <root>
    <appender-ref ref="General" />
  </root>
</log4net>

However, when we run the app, no log file is created (and no logging done). There are no error messages output to the console.

If we move the contents of the Log.config file back into the App.config (replacing the first code line above), it works as expected. Any idea why it is not working in an external file?

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
Robert Wagner
  • 17,515
  • 9
  • 56
  • 72
  • I ran into the same problem - we probably followed the same (mis-guided) guide! – Zach Burlingame Jan 30 '09 at 16:45
  • 14
    This is what I don't like about log4net. The logging framework should be one of the most solid bits of your app in my opinion - but log4net often seems to be a bit flakey. – UpTheCreek Apr 17 '10 at 15:56

14 Answers14

120

Do you have the following attribute in your AssemblyInfo.cs file:

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

and code like this at the start of each class that requires logging functionality:

private static readonly ILog log = 
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

I have a blog post containing this and other info here.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 18
    This works, make sure you if you create the log4net.config file to set the "Copy to Output Directory" property on "Copy Always". – E. van der Spoel Jul 08 '15 at 08:38
  • 1
    @mitchwheat Absolutely god like, i've been battling with a ninject based solution to do exactly what this does all day ... thanks man! – War Nov 27 '15 at 16:10
  • is this mandatory to have "private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);" in each class? if I have common class to handle log and receving the class name as string parameter. won't it work? – Gopi P Mar 07 '22 at 13:52
42

There is an open defect on this issue. Log4Net does not support the configSource attribute of configuration elements. To use a purely configuration file solution you use the log4net.Config key in appSettings.

Step 1: Include the normal configuration section definition:

<configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>

Step 2: Use the magic log4net.Config key in appSettings.

<appSettings>
      <add key="log4net.Config" value="log4net.simple.config" />
</appSettings>

Step 3: Contribute a patch to fix the handling of configSource.

Precipitous
  • 5,253
  • 4
  • 28
  • 34
  • 5
    A call to log4net.Config.XmlConfigurator.Configure(); should get past this issue with it not reading configSource – Greg Domjan Apr 11 '11 at 20:58
  • This didn't change anything for me. I haven't figured out the issue yet, but I'll try to follow up. – Don Rolling Jan 30 '15 at 17:10
  • 5
    It's important to mark the log4net config file as "copy if newer". If the config file is not copied to the bin folder then it's not gonna work. – Francisco Goldenstein Jul 09 '15 at 14:03
  • This worked for me as-is, and I prefer it to the accepted solution because some of my libraries are used in a web app where the logging is configured in a separate log4net.config and sometimes used in stand-along app where the logging is configured in app.exe.config. This way it's all in the config instead of in the assembly info - I don't want to "hard-code" it to log4net.config – Danny Apr 08 '20 at 21:50
30

The step that has been missed is

log4net.Config.XmlConfigurator.Configure(); 

this will cause the configSource to be used. Make sure you call it once before calling GetLogger();

Greg Domjan
  • 13,943
  • 6
  • 43
  • 59
  • You do not need to do this if you use Mitch Wheat's solution. – Robert Wagner Apr 11 '11 at 22:20
  • 4
    @Robert: Sure, though Mitch Wheat's solution requires hard coding the config file outside of the app.config - I read the original question was why doesn't configSource work, it does work if this extra step is followed. – Greg Domjan Apr 12 '11 at 22:45
  • I like this approach more, especially because I create a wrapper log handler which internally use log4net ( which could be replaced later), then in this wrapper log handler I alwasy call log4net.Config.XmlConfigurator.Configure(). In this way, any project with its own app.config could use this wrapper log handler, without needing to change assembler.cs – zheng yu Dec 19 '17 at 12:39
  • Where should I call it? – Yola Dec 16 '20 at 22:48
  • @Yola call it once before calling GetLogger – Greg Domjan Jan 08 '21 at 08:18
22

Make sure that your log4net.config file is set with the following properties:

Build Action: Content

Copy to output directory: Copy Always

Lewis Moten
  • 229
  • 2
  • 2
11

Either use,

<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<appSettings>
<add key="log4net.Config" value="Log4Net.config" />
</appSettings>

or just,

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("Log4Net.config"));

In both cases the file,Log4Net.config, should be there in output directory. You can do this by setting Log4Net.config file properties in solution explorer. Build Action - Content and Copy to Output Directory - Copy always

Byju
  • 187
  • 2
  • 5
3

It is also possible to turn on a Debug mode for log4net. Insert this into the App.config file:

 <appSettings>
      <add key="log4net.Internal.Debug" value="true"/>
 </appSettings>
 <system.diagnostics>
      <trace autoflush="true">
      <listeners>
           <add
             name="textWriterTraceListener"
             type="System.Diagnostics.TextWriterTraceListener"
             initializeData="link\to\your\file.log" />
      </listeners>
      </trace>
 </system.diagnostics>

and you will at least get error messages, from which you can derive what exactly went wrong. In my case I simply forgot to set Copy to output directory to Copy Always.

waka
  • 3,362
  • 9
  • 35
  • 54
2

Watch out for this issue...

In my case everything was configured correctly. The problem is that I used Web Deploy inside Visual Studio 2013 to upload the site to WinHost.com and it reset the ACLs on the server. This in turn revoked all permission on folders and files - log4net could not write the file.

You can read more about it here:

How to stop Web Deploy/MSBuild from messing up server permissions

I asked the support team there to reset the ACLs and then log4net started spitting logs. :)

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
1

Assuming you had an external config file called log4net.config that is copied to your deploy directory you can configure it like so:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Reflection;

using log4net;

namespace MyAppNamespace {
    static class Program {
        //declare it as static and public so all classes in the project can access it
        //like so: Program.log.Error("got an error");
        public static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
             //configure it to use external file
            log4net.Config.XmlConfigurator.Configure(new Uri(Application.StartupPath + "\\log4net.config"));
            //use it
            log.Debug("#############   STARING APPLICATION    #################");


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormMain());
        }
    }
}
Philipp M
  • 1,877
  • 7
  • 27
  • 38
JJ_Coder4Hire
  • 4,706
  • 1
  • 37
  • 25
1

I had the same problem, besides having

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net")]

in the running project, I also had the following line in a reference project:

[assembly: log4net.Config.XmlConfigurator]

When I removed this line in the referenced projects, the logs start to appear.

TheGuest
  • 415
  • 1
  • 4
  • 14
1
  1. add following to AssemblyInfo.cs

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

  2. Make sure log4net.config is included in project

  3. In properties of log4net.config

change CopyToOutputDirctory tag to CopyIfNewer tag

  1. Double check log level level value="ALL"
Amin Golmahalleh
  • 3,585
  • 2
  • 23
  • 36
e03050
  • 1,392
  • 15
  • 12
0

@Mitch, It turns out there is a file with the [assembly:...] declaration, but it did not have the ConfigFile property.

Once I added it and pointed it to Log.config, it started working. I would have thought that it would work like all the other config sections (ie AppSettings) and accept external config files with no modification.

We don't have the second statement you mentioned, as we wrap it in a global static log provider.

Robert Wagner
  • 17,515
  • 9
  • 56
  • 72
0

In my case I got this error message:

log4net: config file [C:\........\bin\Debug\log4net.config] not found.

And log4net.config the file was in Visual Studio 2017 project, but when I checked the file in bin\Debug folder I could not find it.

My original assembly setup was like this:

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

After some research time, I change it to the following and it works:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"..\..\log4net.config", Watch = true)]
Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
0

It's also worth pointing out that in a web app it looks in the root directory, not the bin folder, so make sure that's where you put the config file.

Richard
  • 3,207
  • 5
  • 30
  • 35
0

Adding debug = "true" to the tag <log4net> (i.e. <log4net debug="true">) can help to solve the problem.