How to Do Logging in C# With Log4net

When an application or server crashes, a log simplifies troubleshooting

Woman Working on Laptop Opposite her Friend
Cavan Images/Iconica/Getty Images

When you write computer code in C#, it's a good idea to include logging code. That way, when something goes wrong, you know where to start looking. The Java world has been doing this for years. You can use log4net for this purpose. It is part of Apache log4j 2, a popular open-source logging framework.

This isn't the only .NET logging framework; there are many. However, the Apache name is trusted and the original Java logging framework has been around for more than 15 years.

Why Use a Log4net Logging Framework?

When an application or server crashes, you are left wondering why. Was it a hardware failure, malware, maybe a Denial of Service attack, or some odd combination of keys that manages to bypass all your code checks? You just don't know.

You need to find out why a crash occurred so it can be corrected. With logging enabled, you might be able to see why it happened.

Getting Started

Download the log4net file from the Apache log4net website. Verify the integrity of the downloaded files using the PGP signature or MD5 checksums. The checksums are not as strong indicators as the PGP signature.

Using Log4net

Log4net supports seven levels of logging from none to all in increasing priority. These are:

  1. OFF
  2. FATAL
  3. ERROR
  4. WARN
  5. INFO
  6. DEBUG
  7. ALL

The higher levels include all the lower ones. When debugging, using DEBUG shows all, but on production, you might only be interested in FATAL.

This choice can be made at the component level programmatically or in an XML Config file.

Loggers and Appenders

For flexibility, log4net uses loggers, appenders and layouts. A logger is an object that controls logging and is an implementation of the ILog interface, which specifies five boolean methods: isDebugEnabled, IsInfoEnabled, IsWarnEnabled, IsErrorEnabled and IsFatalEnabled.

It also specifies the five methods—Debug, Info, Warn, Error andFatal—along with overloads and five formatted string versions. You can see the full ILog interface in the log4net online manual.

Loggers are assigned one of the levels but not ALL or OFF, only the other five.

Appenders control where the logging goes. It can be into a database, to an in-memory buffer, to the console, to a remote host, to a text file with rolling logs, the Windows Event Log, or even to email via SMTP. There are 22 appenders in all, and they can be combined so you have plenty of choices. Appenders are appended (hence the name) to a logger.

Appenders filter events by matching substrings, event level, range of levels and start of the logger name.


Finally there are seven layouts that can be associated with an Appender. These control how the event's message is logged and can include exception text, timestamp layouts and XML elements.

Configuring With XML

Although configuring can be done programmatically, it can also be done with XML Config files. Why would you prefer config files over code changes? Simple, it's far easier to have a support guy make a change to a config file than have to get a programmer to change code, test and redeploy a new version.

So config files are the way to go. The simplest possible path is to add App.config your project, as shown in the example below:

<?xml version="1.0" encoding="utf-8" ?>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
      <level value="DEBUG"/>
      <appender-ref ref="LogFileAppender" />
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
      <file value=" log.txt"/>
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c %m%n" />

The log4net online documentation explains all the config file fields.  Having set up App.config, add using log4net and this line:

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

Plus the actual logger has to be fetched with a call to LogManager.GetLogger(...). The GetLogger is usually called with the typeof(class) that it's used in, but this function call also fetches that:


This example shows both in with one commented, so you can choose. 

using log4net;

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

namespace gvmake
    class Program
        private static readonly ILog log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod
().DeclaringType) ;
        //private static readonly ILog log = LogManager.GetLogger(typeof (Program)) ;
        static void Main(string[] args)
            log.Debug("Application Starting") ;