Click here to Skip to main content
15,887,027 members
Articles / Programming Languages / C#
Tip/Trick

Log4Net Singleton Wrapper for Concurrent Logging

Rate me:
Please Sign up or sign in to vote.
4.67/5 (3 votes)
5 Dec 2017CPOL1 min read 16.4K   503   7   4
Solution to show how to "wrap" Log4Net to make it concurrent (as a worker thread)

Image 1

Introduction

There have been numerous questions, as well as my experiences with companies who use Log4Net (see https://logging.apache.org/log4net/) regarding how the use of Log4Net affects the application it is being used in.

Background

I have seen Log4Net being used at four different companies, in each case, it has been assumed that the effect of logging on the application is relevant or is not a considerative factor.

For most applications, I would agree that there is really no cause for concern, however, being aware of the effects and providing a solution to those effects is a necessary understanding for implementing a logging strategy.

The out-of-the box implementation of Log4Net implementation is (I have seen many questions on this) thread-safe, logging can be accomplished from many threads. However, the logging process, which is actuated by appenders can be a problem. Log4Net passes the log to the Appenders and blocks until all the appenders have received the log message

For applications which do not have extensive logging, or the logging load is not large and concurrent, this does not present a problem. This is not the case otherwise.

Using the Code

The console application "Log4NetWrapper" demo application to show the results of "out-of-the-box" logging verses an application that uses Log4Net for concurrent logging. It shows the average amount of time added to the application for logging for "out-of-box" and for concurrent logging.

Out of the Box logging:

C#
//
// Needed for out-of-box logging
//
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger
                (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
...
private static long NormalLogTest()
{
    Stopwatch sw = Stopwatch.StartNew();

    _log.Info("Normal Input 1");
    _log.Info("Normal Input 2");
    _log.Info("Normal Input 3");

    sw.Stop();

    return sw.ElapsedTicks;
}

Concurrent logging:

C#
private static long ConcurrentLogTest()
{
    Stopwatch sw = Stopwatch.StartNew();

    Logger.Instance().Info("Spooled Input 1");
    Logger.Instance().Info("Spooled Input 2");
    Logger.Instance().Info("Spooled Input 3");

    sw.Stop();

    return sw.ElapsedTicks;
}

Executing and Summarizing execution:

C#
long normalTotal = 0;
long concurrentTotal = 0;

for (var i = 0; i < 2; i++)
{
normalTotal += NormalLogTest();
}

for (var i = 0; i < 2; i++)
{
concurrentTotal += ConcurrentLogTest();
}

Console.WriteLine();
Console.WriteLine("Summary of results");

var averageForNormal = normalTotal / 2;
var averageForConcurrent = concurrentTotal / 2;

Console.WriteLine("Application time for normal logging: {0} ticks,
                  {1} milliseconds", averageForNormal, averageForNormal / 10000);
Console.WriteLine("Application time for concurrent logging: {0} ticks,
                  {1} milliseconds", averageForConcurrent, averageForConcurrent / 10000);

Points of Interest

I added a generic class to easily make a concurrent queue (a.k.a. a spooler), please feel free to reuse as needed.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Website: http://www.somedeveloper.us

Comments and Discussions

 
QuestionDo we really need this? Pin
AndyP19657-Dec-17 23:35
professionalAndyP19657-Dec-17 23:35 
AnswerRe: Do we really need this? Pin
Member 138083834-May-18 3:08
Member 138083834-May-18 3:08 
QuestionIsn't there a downside to this? Pin
George Swan5-Dec-17 21:18
mveGeorge Swan5-Dec-17 21:18 

Thanks for the interesting tip, Jeff. It seems to me that you are creating a new instance of the logger for every message you log when you use the concurrent method. The recommended approach is to use a new instance for every class that implements logging. This simplifies debugging as you can easily trace the messages logged by that class and it is a good compromise between performance and convenience.


AnswerRe: Isn't there a downside to this? Pin
Jeff Bramlett4-Nov-18 5:27
Jeff Bramlett4-Nov-18 5:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.