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:

using log4net;
using log4net.Core;
using log4net.Repository.Hierarchy;
using log4net.Appender;
using log4net.Layout;
using log4net.Filter;

A file appender

        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;
        }

A console appender

        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;
        }

An ADO.NET appender

        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;
        }

The above requires 3 helper functions:

        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);
        }
        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);
        }
        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);
        }

Initializing log4net

Now you can easily initialize log4not in the startup of your application. Here are some extra helper functions:

        public static void ConfigureWithFile(string appCode)
        {
            var h = (Hierarchy)LogManager.GetRepository();
            h.Root.Level = Level.All;
            h.Root.AddAppender(CreateFileAppender(appCode));
            h.Configured = true;
        }
        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;
        }

So now, if example you have a web application:

protected void Application_Start(object sender, EventArgs e)
{
LogHelpers.ConfigureWithDb(@"Data Sourc
e=.\SQL2008;Initial Catalog=Today;Integrated Security=True",false); LogHelpers.ConfigureWithFile("MyWebApp"); }

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:

public static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));

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.