Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Log4Net in multithreaded environment

Tags:

c#

log4net

I have a Multi-Threaded environment where application starts from WPF, which initiates 2 background worker threads a web socket server and a Web API server.

I want to log all the events in a single log file. I am using log4Net(for the first time).

I am creating 3 instances of Logger and assuming that the file appender will understand that it has to write to a single file only.

Code:

Logger Class:

public class Logger  :ILogger
{
    private static ILog log = null;
    static Logger()
    {
        log = LogManager.GetLogger(typeof(Logger));
        GlobalContext.Properties["host"] = Environment.MachineName;
    }
    public Logger(Type logClass)
    {
        log = LogManager.GetLogger(logClass);
    }

    #region ILogger Members
    public void LogException(Exception exception)
    {
        if (log.IsErrorEnabled)
            log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", exception.Message), exception);
    }
    public void LogError(string message)
    {
        if (log.IsErrorEnabled)
            log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", message));
    }
    public void LogWarningMessage(string message)
    {
        if (log.IsWarnEnabled)
            log.Warn(string.Format(CultureInfo.InvariantCulture, "{0}", message));
    }
    public void LogInfoMessage(string message)
    {
        if (log.IsInfoEnabled)
            log.Info(string.Format(CultureInfo.InvariantCulture, "{0}", message));
    }
    #endregion
}

Log Config:

    <log4net debug="true">
  <appender name="RollingLogFileAppender"
              type="log4net.Appender.RollingFileAppender">
    <file value="/pathToLogFile" />
    <staticLogFileName value="false"/>
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value=" yyyy-MM-dd&quot;.txt&quot;"/>
    <layout type="log4net.Layout.PatternLayout">
      <!--<param name="ConversionPattern" 
               value="%d [%t] %-5p %c %m%n" />-->
      <conversionPattern
         value="%date [%thread] %-5level %logger ==> %message%newline"/>
    </layout>
  </appender>

  <root>
    <level value="INFO" />
    <appender-ref ref="RollingLogFileAppender" />
    <appender-ref ref="AdoNetAppender" />
  </root>
</log4net>

I am creating 3 instances of Logger, in 3 different projects like:

static ILogger logger = new Logger(typeof(MainWindow));
static ILogger logger = new Logger(typeof(DefaultApiController));
static ILogger logger = new Logger(typeof(WebSocket));

But, The log file has only the WebSocket log. Is there a loophole in my understanding? Where am I going wrong?

Basically, there are 3 threads running, so definitely I can't pass in the same Logger object from one to other.

like image 340
XYZ Avatar asked Jun 21 '17 17:06

XYZ


1 Answers

Your main issue is that you are using a static logger but trying to assign that static variable 3 different times in your instance's constructor, the last one will always win. The number of projects does not matter, if all projects are hosted in the same running executable there will only ever be 1 instance of Logger::log (assuming you are not creating multiple application domains).

public class Logger  :ILogger
{
    private static ILog log = null;
    static Logger()
    {
        log = LogManager.GetLogger(typeof(Logger));
        GlobalContext.Properties["host"] = Environment.MachineName;
    }
    public Logger(Type logClass)
    {
        log = LogManager.GetLogger(logClass);
    }

Should be

public class Logger  :ILogger
{
    private ILog log = null;
    public Logger(Type logClass)
    {
        log = LogManager.GetLogger(logClass);
    }

That said I am not sure why you are trying to set it up this way. It is much easier to supply a static logger in any class that needs one. Example:

public class SomeInterestingType {
  private static readonly ILog Logger = LogManager.GetLogger(typeof(SomeInterestingType));

  public void DoSomething() {
    Logger.Info("Busy doing something");
  }
}

And then just repeat that pattern.

like image 111
Igor Avatar answered Oct 08 '22 16:10

Igor