在多线程环境中使用 Log4Net
Using Log4Net in multithreaded environment
我有一个多线程环境,应用程序从 WPF 启动,它启动 2 个后台工作线程,一个 Web 套接字服务器和一个 Web API 服务器。
我想将所有事件记录在一个日志文件中。我正在使用 log4Net(第一次)。
我正在创建 Logger 的 3 个实例,并假设文件附加程序将理解它必须只写入一个文件。
代码:
记录器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
}
日志配置:
<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>
我正在 3 个不同的项目中创建 3 个 Logger 实例,例如:
static ILogger logger = new Logger(typeof(MainWindow));
static ILogger logger = new Logger(typeof(DefaultApiController));
static ILogger logger = new Logger(typeof(WebSocket));
但是,
日志文件只有 WebSocket
日志。我的理解有漏洞吗?我哪里错了?
基本上,有 3 个线程 运行,所以我绝对不能将同一个 Logger 对象从一个线程传递到另一个线程。
您的主要问题是您使用的是静态记录器,但尝试在实例的构造函数中为该静态变量分配 3 次不同的时间,最后一次总是获胜。项目的数量无关紧要,如果所有项目都托管在同一个 运行 可执行文件中,则只会有 1 个 Logger::log
实例(假设您没有创建多个应用程序域).
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);
}
应该是
public class Logger :ILogger
{
private ILog log = null;
public Logger(Type logClass)
{
log = LogManager.GetLogger(logClass);
}
也就是说,我不确定您为什么要尝试以这种方式进行设置。在任何需要静态记录器的 class 中提供静态记录器要容易得多。示例:
public class SomeInterestingType {
private static readonly ILog Logger = LogManager.GetLogger(typeof(SomeInterestingType));
public void DoSomething() {
Logger.Info("Busy doing something");
}
}
然后重复那个模式。
我有一个多线程环境,应用程序从 WPF 启动,它启动 2 个后台工作线程,一个 Web 套接字服务器和一个 Web API 服务器。
我想将所有事件记录在一个日志文件中。我正在使用 log4Net(第一次)。
我正在创建 Logger 的 3 个实例,并假设文件附加程序将理解它必须只写入一个文件。
代码:
记录器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
}
日志配置:
<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>
我正在 3 个不同的项目中创建 3 个 Logger 实例,例如:
static ILogger logger = new Logger(typeof(MainWindow));
static ILogger logger = new Logger(typeof(DefaultApiController));
static ILogger logger = new Logger(typeof(WebSocket));
但是,
日志文件只有 WebSocket
日志。我的理解有漏洞吗?我哪里错了?
基本上,有 3 个线程 运行,所以我绝对不能将同一个 Logger 对象从一个线程传递到另一个线程。
您的主要问题是您使用的是静态记录器,但尝试在实例的构造函数中为该静态变量分配 3 次不同的时间,最后一次总是获胜。项目的数量无关紧要,如果所有项目都托管在同一个 运行 可执行文件中,则只会有 1 个 Logger::log
实例(假设您没有创建多个应用程序域).
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);
}
应该是
public class Logger :ILogger
{
private ILog log = null;
public Logger(Type logClass)
{
log = LogManager.GetLogger(logClass);
}
也就是说,我不确定您为什么要尝试以这种方式进行设置。在任何需要静态记录器的 class 中提供静态记录器要容易得多。示例:
public class SomeInterestingType {
private static readonly ILog Logger = LogManager.GetLogger(typeof(SomeInterestingType));
public void DoSomething() {
Logger.Info("Busy doing something");
}
}
然后重复那个模式。