Logging with log4net in .NET Core 3.0 Console App

I decided to write this post because, with this seemingly simple thing, containing a little bunch of code, I encountered extremely many problems and errors. In this post, I will go through the setup of logging with log4net in the .NET Core 3.0 console application and try to solve some of the common issues you can encounter during this process.

A refreshed version of this blog post adjusted to .NET 7 is available.

Logging with log4net in .NET 7 Console App

Project setup

In this tutorial, I will use .NET Core 3.0, log4net v2.0.8, and Visual Studio Community 2019. Start with creating a new project using Console App (.NET Core) template.

Log4Net Installation

When your solution is ready, you need to add the log4net package to your project. To do this run the following command in your NuGet console:

PM> Install-Package log4net

If you’re using Visual Studio you can do this also through the NuGet Package Manager window. Click RMB on your project in the Solution Explorer window and choose Manage Nuget Packages… Then search for log4net in the Browse tab. Click on log4net and install the latest version of the package.

NuGet Package installation window.

Add config file

Add a new file called log4net.config in the project root level and populate it with the content from the code frame below. It adds two types of log appenders – one which will save our application logs to file and the second one which prints them into the console window.

<log4net>
    <root>
        <level value="ALL" />
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>
    <appender name="console" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level %logger - %message%newline" />
        </layout>
    </appender>
    <appender name="file" type="log4net.Appender.RollingFileAppender">
        <file value="main.log" />
        <appendToFile value="true" />
        <rollingStyle value="Size" />
        <maxSizeRollBackups value="5" />
        <maximumFileSize value="25MB" />
        <staticLogFileName value="true" />
        <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
        </layout>
    </appender>
</log4net>

Load Configuration

When configuring log4net in my project, I followed this tutorial. According to this, in point no. 3 I should add a line at the bottom of the AssemblyInfo.cs file, but… I didn’t have this file. It turns out that in .NET Core 3.0 assembly file is generated automatically, and the whole configuration should be done through csproj file. After a quick research, I’ve found out that the configuration can be manually loaded from log4net.config file in the application code level, before any other code, will be executed.

using log4net;
using log4net.Config;
using System;
using System.IO;
using System.Reflection;

namespace NetCore3Log4Net.Tutorial.ConsoleApp
{
    class Program
    {
        private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            // Load configuration
            var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
            XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));

            Console.WriteLine("Hello world!");

            // Log some things
            log.Info("Hello logging world!");
            log.Error("Error!");
            log.Warn("Warn!");

            Console.ReadLine();
        }
    }
}

If we run our program now, the console still displays only the “Hello world!” text. The reason for this behavior is that by default log4net.config file is not copied to the output directory, which means that Configure method that we’ve set up in the previous step can’t find the file to load the configuration. To fix this issue, right-click on log4net.config file and choose Properties. Then change the option under Copy to Output Directory build action into Copy if newer or Copy always.

Change Copy to Output Directory build action into Copy if newer.

Here it is! Our logging configuration is completed. We can see our logs in the console, and also they’re stored in a text file, which is by default saved under the path:

~\<project_name>\bin\Debug\netcoreapp3.0

Colored Console Appender

Our logging is ready, but as you can see in the screen above, at first glance it’s difficult to distinguish which logs indicate application errors, and which are only informational. Hopefully, log4net provides a specific appender to make console logs colorful. As I found here, it just needs the replacement of the regular ConsoleAppender with the ColoredConsoleAppender and adding a few lines to the configuration file, containing log types mapping into individual colors. But, it doesn’t work for me.

After quite a long research about my issue and 100 times verifications that I did make no mistake in the configuration file, I found this repository. And exactly this comment:

https://gist.github.com/mizanRahman/4484020

I’ve followed the suggestion and replaced ColoredConsoleAppender with ManagedColoredConsoleAppender. Et… voila! Our colored console logging works perfectly.

And final look on log4net.config file:

<log4net>
  <root>
    <level value="ALL" />
    <appender-ref ref="console" />
    <appender-ref ref="file" />
  </root>
  
  <!--File Appender-->
  <appender name="file" type="log4net.Appender.RollingFileAppender">
    <file value="main.log" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="25MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
    </layout>
  </appender>
  
  <!--Console appender-->
  <appender name="console" type="log4net.Appender.ManagedColoredConsoleAppender">
    <mapping>
      <level value="INFO" />
      <forecolor value="Green" />
    </mapping>
    <mapping>
      <level value="WARN" />
      <forecolor value="Yellow" />
    </mapping>
    <mapping>
      <level value="ERROR" />
      <forecolor value="Red" />
    </mapping>
    <mapping>
      <level value="DEBUG" />
      <forecolor value="Blue" />
    </mapping>
    <layout type="log4net.Layout.PatternLayout">
      <conversionpattern value="%date [%thread] %-5level - %message%newline" />
    </layout>
  </appender>
</log4net>

I hope that my post will prove useful, help you prepare your logging mechanism quickly and make this process as nice as possible.

Sources

Advertisement

9 thoughts on “Logging with log4net in .NET Core 3.0 Console App

  1. Aw, this was quite a good post. In concept I have to place in writing similar to this moreover – spending time and actual effort to make a excellent article… but what / things I say… I procrastinate alot and no indicates often get something carried out.

    Like

  2. Thanks for this tip – it saved me a lot of frustration!
    I love the color logger, but I think log4net is starting to die in the .NET Core world.
    One thing – the color configs in the .config file are slightly different – before we had “HighIntensity” (e.g. “Red, HighIntensity” but this does not work any more. They need to be here:
    https://docs.microsoft.com/en-us/dotnet/api/system.consolecolor?redirectedfrom=MSDN&view=net-5.0

    Liked by 1 person

  3. Came across this page trying to do this in a .net 5/6 project. Found that I had to do this in order to get these steps to work:

    1. (Maybe optional) Run ‘Install-PackageProvider Nuget –force –verbose’ (see https://stackoverflow.com/questions/58351619/install-package-dependency-loop-detected-for-package-microsoft-data-sqlite)
    2. Use this command to install, otherwise it gets stuck in a dependency loop: ‘install-package log4net -SkipDependencies’ (same link as above)
    3. Run `dotnet add package log4net` after installing it.

    As far as I can tell, the only non-build-related thing #3 does is add this to the csproj file:

    https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-reference

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s