Log4net for .Net Core 2.0

Log4net is a an excellent library that allows developers to output log statements to a variety of output targets through what is called Appenders. However, it’s not compatible with .Net Core 2.0 yet, and all the online log4net extension libraries available today don’t provide a thorough solution to rectify all log4net appenders specifically the ADOAppender; which logs to a database.  In this article I am going to introduce a solution to this problem.

I have uploaded the solution to GitHub at this URL:  https://github.com/rizksobhi/Log4net.NetCore

1- AdoNetAppender

I have created an appender that is compatible with .Net Core that can be used to log to a database. The code is straight forward and I have imported most of it from the log4net library. https://github.com/rizksobhi/Log4net.NetCore/blob/master/Log4net.NetCore.Lib/Appenders/AdoNetAppender.cs

2- Configuration file replacements

I have substituted the configuration file with a static configuration class which provides several ways of creating a variety of appenders. This configuration class uses the AdoNetAppender which is described above.

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

    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");
    AddErrorParameterToAppender(appender, "@exception", 2000);

    appender.ActivateOptions();
    return appender;
}

3- ASP.Net Core integration

The following extension method helps to register log4net in the logging factory

public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, string connectionString, string logFilePath)
{
    factory.AddProvider(new Log4NetProvider(connectionString, logFilePath));
    return factory;
}

Now we can register our log4net provider through using the extension method at the Configure function in Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, Log4netDBContext context, ILoggerFactory loggerFactory)
{
    loggerFactory.AddLog4Net(Configuration["Logging:ConnectionString"], Configuration["Logging:LogFilePath"]);

    DBInitializer.Initialize(context);

    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }
            
    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Here is the implementation of Log4NetProvider https://github.com/rizksobhi/Log4net.NetCore/blob/master/Log4net.NetCore.Lib/Log4NetProvider.cs

And finally using in the HomeController

public HomeController(ILogger logger)
{
    _Logger = logger;
}
public IActionResult Index()
{
    _Logger.LogDebug("Index has been requested");
    return View();
}

References

  1. https://github.com/apache/logging-log4net
  2. https://dotnetthoughts.net/how-to-use-log4net-with-aspnetcore-for-logging/