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".txt""/>
<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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With