Creating Log4Net appenders programatically in C#

In most cases using log4net’s xml configuration is best to set up how your application will log. However I found it more practical to create the configuration programatically in a shared c# file, to easily add common options between my applications. First create a static class to hold the following methods and add using:
[sourcecode language=”csharp”]
using log4net;
using log4net.Core;
using log4net.Repository.Hierarchy;
using log4net.Appender;
using log4net.Layout;
using log4net.Filter;
[/sourcecode]

A file appender

[sourcecode language=”csharp”]
public static IAppender CreateFileAppender(string appCode)
{
var appender = new RollingFileAppender
{
Name = "RollingFileAppender",
File = String.Format(@"C:\logs\{0}.log", appCode),
AppendToFile = false,
RollingStyle = RollingFileAppender.RollingMode.Size,
MaxSizeRollBackups = 10,
MaximumFileSize = "100MB"
};

var layout = new PatternLayout
{
ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
};

layout.ActivateOptions();

appender.Layout = layout;
appender.ActivateOptions();

return appender;
}
[/sourcecode]

A console appender

[sourcecode language=”csharp”]
public static IAppender CreateConsoleAppender()
{
var appender = new ConsoleAppender {Name = "ConsoleAppender"};
var layout = new PatternLayout
{
ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
};

layout.ActivateOptions();
appender.Layout = layout;
appender.ActivateOptions();

return appender;
}
[/sourcecode]

An ADO.NET appender

[sourcecode language=”csharp”]
public static IAppender CreateAdoNetAppender(string cs)
{
var appender = new AdoNetAppender
{
Name = "AdoNetAppender",
BufferSize = 1,
ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
ConnectionString = cs,
CommandText = @"INSERT INTO Log ([Date], [Thread], [Level], [Logger], [Message], [Exception], [User], [Ip]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, @user, @ip)"
};

AddDateTimeParameterToAppender(appender, "log_date");
AddStringParameterToAppender(appender, "thread", 255, "%thread");
AddStringParameterToAppender(appender, "log_level", 50, "%level");
AddStringParameterToAppender(appender, "logger", 255, "%logger");
AddStringParameterToAppender(appender, "message", 4000, "%message");
AddStringParameterToAppender(appender, "user", 50, "%aspnet-request{AUTH_USER}");
AddStringParameterToAppender(appender, "ip", 15, "%aspnet-request{REMOTE_ADDR}");
AddErrorParameterToAppender(appender, "exception", 2000);
appender.ActivateOptions();

return appender;
}
[/sourcecode]

The above requires 3 helper functions:

[sourcecode language=”csharp”]
public static void AddStringParameterToAppender(this AdoNetAppender appender, string paramName, int size, string conversionPattern)
{
var param = new AdoNetAppenderParameter
{
ParameterName = paramName,
DbType = System.Data.DbType.String,
Size = size,
Layout = new Layout2RawLayoutAdapter(new PatternLayout(conversionPattern))
};
appender.AddParameter(param);
}
[/sourcecode]
[sourcecode language=”csharp”]
public static void AddDateTimeParameterToAppender(this AdoNetAppender appender, string paramName)
{
var param = new AdoNetAppenderParameter
{
ParameterName = paramName,
DbType = System.Data.DbType.DateTime,
Layout = new RawUtcTimeStampLayout()
};
appender.AddParameter(param);
}
[/sourcecode]
[sourcecode language=”csharp”]
public static void AddErrorParameterToAppender(this AdoNetAppender appender, string paramName, int size)
{
var param = new AdoNetAppenderParameter
{
ParameterName = paramName,
DbType = System.Data.DbType.String,
Size = size,
Layout = new Layout2RawLayoutAdapter(new ExceptionLayout())
};
appender.AddParameter(param);
}
[/sourcecode]

Initializing log4net

Now you can easily initialize log4not in the startup of your application. Here are some extra helper functions:
[sourcecode language=”csharp”]
public static void ConfigureWithFile(string appCode)
{
var h = (Hierarchy)LogManager.GetRepository();
h.Root.Level = Level.All;
h.Root.AddAppender(CreateFileAppender(appCode));
h.Configured = true;
}
[/sourcecode]
[sourcecode language=”csharp”]
public static void ConfigureWithDb(string cs, bool onlyErrors)
{
var h = (Hierarchy)LogManager.GetRepository();
h.Root.Level = Level.All;

var ado = CreateAdoNetAppender(cs);
h.Root.AddAppender(ado);

if (onlyErrors)
{
var filter = new LevelRangeFilter {LevelMin = Level.Error};
((AppenderSkeleton)ado).AddFilter(filter);
}

h.Configured = true;
}
[/sourcecode]
So now, if example you have a web application:
[sourcecode language=”csharp”]
protected void Application_Start(object sender, EventArgs e)
{
LogHelpers.ConfigureWithDb(@"Data Source=.\SQL2008;Initial Catalog=Today;Integrated Security=True",false);
LogHelpers.ConfigureWithFile("MyWebApp");
}
[/sourcecode]
The above would log to the database (only the errors) plus a file (all log levels). The rest is all the same, e.g. to get the logger instance:
[sourcecode language=”csharp”]
public static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));
[/sourcecode]
via: http://codesofair.wordpress.com/2012/02/01/creating-log4net-appenders-programatically-in-c/

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.