28

I understand that this question has been asked several times, but unfortunately, I haven't been able to get my logging configuration working. I have to be making some very small mistake somewhere.

I have a .NET 4.5 MVC 4/EF 5 web application and I'm trying to get logging to work. The solution has two projects, one for the DAO's and model objects, and one for the web site. The App.Config file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="RebuildingTogetherEntities" connectionString="stuff..."/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <log4net configSource="Log.config" />
</configuration>

The same log4net section has also been copied into the Web.Config file.

I added the following to both AssemblyInfo.cs files:

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

"Copy To Output Directory" is set to true for both Log.Config files.

The only way that I can seem to get logging to append to the output file is to call XmlConfigurator.Configure() before the first logging statement runs. I guess I can write a facade to do that when I first obtain the logger, but that just feels wrong.

How can I initialize the logger without calling the XmlConfigurator manually?

Community
  • 1
  • 1
Brad
  • 2,261
  • 3
  • 22
  • 32
  • Does http://stackoverflow.com/questions/3971250/log4net-configuration-from-assembly-attribute-does-not-load-configuration-file apply? – sgmoore May 27 '13 at 09:03
  • It would appear not... in that case, there was a message from log4net before application shutdown, but I don't see that message in my case. Thanks for the suggestion, though. – Brad May 27 '13 at 15:03
  • 1
    Not sure I agree with your logic. You won't see the log4net message unless internal logging is on, and if your system isn't reading your log.config then it probably won't be on. The important point is that when you do something like GetLogger(...) the system will basically do something equivalent to Attribute.GetCustomAttributes(Assembly.GetCallingAssembly(), typeof(log4net.Config.ConfiguratorAttribute), false) . Hence if you don't log very early in your application startup, then your first logger may be initialized from an assembly that does not continue the custom attribute. – sgmoore May 27 '13 at 17:46
  • 11
    I LOVE how logging frameworks FAIL SILENTLY –  Apr 09 '19 at 16:13

2 Answers2

35

I have faced exactly the same issue. As you rightly point out, you should not need to explicitly call XmlConfigurator when you include the line in your AssemblyInfo.cs. The problem comes when the first use of log4net is in an assembly that doesn't have that line. In my case I was using the Topshelf.Log4Net NuGet package, and the first log line that my application logged was through that.

You could just log a line early in your app or if you don't need to log anything do what I did and add the following at the entry point of the application

LogManager.GetLogger(typeof(Program));
Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
Matt Cole
  • 2,491
  • 17
  • 21
  • Great answer. We had the same problem where an object that was being auto created by our DI container was spitting out a line of logging before the main application. – BBoy Dec 14 '16 at 00:45
  • What a life saver. Put it in global.asax.cs and it worked perfectly. Spent literally a day for this. – arviman Feb 28 '17 at 13:24
  • What is Program in this case? – Euridice01 Oct 19 '17 at 15:30
  • 1
    A `Program` class is commonly used as the entry point for C# apps. You could use any class from your entry assembly though. – Matt Cole Oct 19 '17 at 15:55
  • 1
    After many google searches, and stackoverflow wrong answers, why hasn't this been marked as the correct answer? – Daniel Lobo Jan 26 '18 at 16:36
  • I am not sure from where LogManager is? I got red highlight. – Hnin Htet Htet Aung Jul 18 '18 at 03:09
  • @HninHtetHtetAung it is used to instantiate loggers in log4net. Have you checked [the documentation](http://logging.apache.org/log4net/release/manual/configuration.html)? – Matt Cole Jul 18 '18 at 21:47
  • 2
    @ChrisGessler this is not a workaround, it is [as specified in the attribute documentation](http://logging.apache.org/log4net/release/manual/configuration.html#attributes) - _"… it is imperative to make a logging call as early as possible during the application start-up, and certainly before any external assemblies have been loaded and invoked."_ – stuartd Dec 04 '18 at 16:18
  • Hurrah! Been banging my head on the table with this one. Thx :) – Fetchez la vache Feb 12 '19 at 12:34
9

You do not need to call the XmlConfigurator manually if you use:

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

However you have to add the tag to all your dlls (all assambly.cs files).

Martin Ba
  • 37,187
  • 33
  • 183
  • 337
Peter
  • 27,590
  • 8
  • 64
  • 84