Saturday, December 7, 2013

log4net.Appender.EventLogAppender and WCF

So I finally cracked the magic behind getting the log4net EventLogAppender to work within a WCF service and very likely any other web related solution.  Initially after pulling my hair out and spending hours pouring over StackedOverflow and log4net postings had I given up any hope of finding a way to get this working.  Most of the solutions offered either sounded scary - for instance like adding the identity of the application pool within the Administrators group on the local machine!?!  Or simply didn't work like the instructions in the documentation over at Apache -which left out crucial step if you are writing WCF or other web projects.  Hopefully if you come across this it might shed some light on the subject, prevent hours of frustration, and get you working.

The documentation over at Apache isn't complete when it comes to setting up log4net to use the Windows event viewer.  While the settings illustrated are precisely correct they leave out a two key ingredients - things which must be done to get this to work.

First there is some meaning behind the log4net proper within the EventLogAppender property called "ApplicationName" which should be set within your web.config.  An example of the confing file can found over at Apache's config examples under the EventLogAppender settings.  However, here is the property that I am specifically speaking about:

<applicationName value="YourAppName" />

This application name actually defines the value that will appear in the "Source" column in the event viewer.

Second, in order to actually write out to the event viewer you need to do some registry work.  Navigate to the following area of your registry (or if you are wanting to write to another section of the event viewer navigate to that):

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application

Within this section (assuming you want the event log's to appear under the Windows Logs/Application section) add a new key that is EXACTLY the same as the ApplicationName defined in above.  Within this key add a new string element called "EventMessageFile" and set the value to:


%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\EventLogMessages.dll

Once this is done reset the application pool and you should start seeing the Application event log entries with the "source" equal to the name of the ApplicationName set in your log4net <appender> group.

In order to avoid having to do all this typing on each of the target servers I'd recommend that you extract the key you added and place that in your project for safe keeping.  This registry file can then be imported into the registry of the target server(s) you are deploying your application.  Adding to the project and eventually to version control will help keep your work around and handy for others.


4 comments:

  1. Hi Michael,

    I think your post is really interesting. I had exactly the same problem, but the solution is slightly different.
    In my case, I was able to use Log4Net on my dev machine, but when I was running the service on a VM, the logging didn't happen. I googled the problem for several hours, then turning on the internal debug of Log4Net allowed me to discover that on my VM I had installed .NET 4.0.
    I am building targeting 4.0 but on my machine there's installed 4.5.2 which is an in-place update.

    Thanks for your post,
    Paolo

    ReplyDelete
    Replies
    1. Thanks for the kind comment. I am curious to know what could have changed between 4.0 and 4.5.2 that would have allowed you to post to the event viewer. Can you elaborate on your solution a bit more?

      Delete
    2. Hi Michael,

      first a clarification: in my VM I have .NET 4.0 client while I am building targeting 4.0 (full) with installed 4.5.2. Log4Net (1.2.13) has been built in the same way: targeting 4.0, using 4.5.2.

      The error reported by log4net is:
      log4net:ERROR [EventLogAppender] ErrorCode: GenericFailure. Failed in DoAppend
      System.TypeLoadException: Could not load type 'System.Security.Claims.ClaimsIden
      tity' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=
      b77a5c561934e089'.
      at log4net.Core.LoggingEvent.get_UserName()
      at log4net.Core.LoggingEvent.CreateCompositeProperties()
      at log4net.Core.LoggingEvent.LookupProperty(String key)
      at log4net.Appender.EventLogAppender.Append(LoggingEvent loggingEvent)
      at log4net.Appender.AppenderSkeleton.DoAppend(LoggingEvent loggingEvent)
      log4net: Shutdown called on Hierarchy [log4net-default-repository]

      From what I can see, it's implicity calling ClaimsIdentity but in a different namespace (in .NET 3.5/4 it's Microsoft.IdentityModel.Claims while .NET 4.5 is System.Security.Claims.

      It's not the first time I experience this type of behaviour, also while using MEF.

      Thanks,
      Paolo

      Delete
    3. Ah yes, .NET 4.5 did move the Identity namespace (and consequently changed the way cookies are encrypted for web clients).

      Again, thanks for sharing. Take care.

      Delete