The following post explains how to get Log4Net working in a .NET console application.
The first step is create your console application and add references to Log4Net. The easiest way to add the correct references is via NuGet, where it is simply listed as log4net.
You’ll need to add a configuration file to tell Log4Net how you want it to log. A basic example would be:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="Test.log" />
<appendToFile value="true" />
<maximumFileSize value="5000KB" />
<maxSizeRollBackups value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%utcdate{yyyy-MM-dd HH:mm:ss.fffffff} - %level - %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
</configuration>
This example simply adds a rolling log file. It’s called rolling because it starts a new log file at triggered intervals, allowing you to delete historical log files when you’ve finished with them. In this case, a new log file is started each time the current log file gets to 5000KB. It’s worth taking a look at the Log4Net documentation to find out about the different types of logging available. It is also possible to write your own appender if you want to do something not already built it to Log4Net.
In order to tell Log4Net to pick your configuration, you need to add the following to your application:
[assembly: XmlConfigurator]
The most obvious place for this is the AssemblyInfo.cs file.
This tells Log4Net to look in the default configuration file for the Log4Net configuration settings, but you can also tell Log4Net to look in another custom configuration file using the overloads available to the XmlConfigurator, although I prefer to keep all configuration in a single file.
Then it’s just a case of using the logger:
using System;
using log4net;
namespace Test
{
public static class Program
{
public static void Main()
{
var log = LogManager.GetLogger(typeof(Program));
log.Debug("Test console application started");
Console.ReadLine();
}
}
}
Note that the LogManager returns an object implementing the ILog interface.
If you’re using dependency injection, you should wire up the dependency injector to return your ILog instance. The following shows how to do this if you’re using Castle Windsor:
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;
using log4net;
namespace Test
{
public static class Injector
{
private static readonly object InstanceLock = new object();
private static IWindsorContainer instance;
public static IWindsorContainer Instance
{
get
{
lock (InstanceLock)
{
return instance ?? (instance = GetInjector());
}
}
}
private static IWindsorContainer GetInjector()
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
RegisterInjector(container);
RegisterLog(container);
return container;
}
private static void RegisterInjector(WindsorContainer container)
{
container.Register(
Component.For<IWindsorContainer>()
.Instance(container));
}
private static void RegisterLog(WindsorContainer container)
{
container.Register(
Component.For<ILog>()
.Instance(LogManager.GetLogger(typeof(Injector)))
.LifestyleSingleton());
}
}
}
The following statement will return an ILog instance as expected:
var log = Injector.Instance.Resolve();
There you have it!