Using Log4Net in a multi-threaded environment

I have a multi-threaded environment in which an application starts from WPF, which initiates 2 background worker threads of a web socket server and a web API server.

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

I am creating 3 instances of Logger and assume that the file appender will understand that it should only write to one file.

code:

Registrar 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 Configuration:

  <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 create 3 instances of Logger in three different projects, such as:

 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 mistaken?

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

+5
source share
1 answer

Your main problem is that you are using a static logger, but trying to assign this static variable 3 times in your instance constructor, the latter will always win. The number of projects does not matter, if all projects are located in one executable executable file, there will be only one instance of Logger::log (provided that you do not create several 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); } 

Must be

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

That says I'm not sure why you are trying to configure it that way. It is much easier to put a static logger in any class that it needs. 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 this pattern.

+7
source

Source: https://habr.com/ru/post/1269075/


All Articles