Setting up Log4Net

Log4Net is a great logging system but can be a little tricky to setup. The ConfigZilla samples contain a log4net.template.config which you can copy-and-paste into your own projects. It gives you 3 appenders (i.e. places where the log messages go).

Setup

It's a good idea to keep the log4net config in a separate file because it tends to be rather long. Remember to add the [assembly] attribute as follows (another benefit of doing it this way is that you don't need the "configSource" setting in your app.config file).

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

In web apps, set the build type of the log4net file to "Content", this will leave it in the root of your website rather than copying it into the bin folder. It seems to be necessary to add this into your Application_Start() event:

log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/log4net.config")));

Create a logger by just copying and pasting this line. It uses fully qualified type names and reflection so you don't need to add any "using" statements or edit the logger name:

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

If you are having trouble getting log4net to work, add the following app setting to your config file. This turns on log4net's internal debugging.

<appSettings>
    <add key="log4net.Internal.Debug" value="true"/>
</appSettings>

Associating "Context Data" with log messages using ThreadContext

A powerful feature of log4net is ThreadContext which allows you to associate arbitrary data with the logging system and then log it automatically when you log a message. For example, if you are dealing with a particular User Id you could associate that User Id with the context, and every message you log will come out with the User Id attached. The question arises as to how to cancel the association: logging the associated data in the wrong context will be confusing. The IDisposable interface provides one way of doing this automatically. The ConsoleSingleConfig sample contains an example of setting up an "associated int" and an "associated string" with the log using two classes, AssocInt and AssocString. These are then dumped out in the SQL log (but not the file logs) via these parameters:

<parameter>
    <parameterName value="@assoc_int" />
    <dbType value="Int64" />
    <layout type="log4net.Layout.RawPropertyLayout">
        <key value="AssocInt" />
    </layout>
</parameter>
<parameter>
    <parameterName value="@assoc_string" />
    <dbType value="String" />
    <size value="255" />
    <layout type="log4net.Layout.PatternLayout" value="%property{AssocString}" />
</parameter>

You can setup as many different types of associated data as you want, it depends on the needs of your app.

Filtering logging

By level

You can set the level filter on a logger, including the root logger. Only messages with at least that level will be logged.

<logger name="My.Name.Space.Class">
    <level value="ERROR" />
    ...
</logger>

Routing classes (loggers) to different destinations

Add another logger with the name property set to the name of the class or namespace that you want to isolate. Add an appender to the logger (it's best to make an appender just for this logger).

<logger name="My.Name.Space">
    <level value="ALL" />
    <appender-ref ref="MyFileAppender />
</logger>

Filtering

Filtering is applied at the appender level. You can apply various filters to the log messages that are coming through. For example, to block all messages from a namespace you can do this:

<appender ....>
    <filter type="log4net.Filter.LoggerMatchFilter">
        <loggerToMatch value="My.Name.Space" />
        <acceptOnMatch value="false" />
    </filter>
    

Further reading


Table Of Contents