2011-08-05 59 views
9

我有一个服务应用程序,它在启动时读取XML文件并为XML文件中的每个条目启动一个线程。每个线程都创建一个工作者类的实例,这需要记录器将任何输出记录到特定于线程的日志文件。为每个单独的线程记录日志文件

在我的app.config有设置为使用XML附加目的地log4net的配置设置和文件被指定为PatternString服务,如下所示:

<appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
    <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
    <immediateFlush value="true"/> 
    <appendToFile value="true" /> 
    <layout type="log4net.Layout.SimpleLayout" /> 
</appender> 

在用于的每个实例的螺纹锁定方法创建的工人类我使用log4net.LogManager.GetLogger("MyLogger")方法得到记录器,然后使用ThreadContext.Properties["LogName"] = "Log name prefix"设置当前线程PatternStrings LogName属性。

所有的文件都被创建,但是当记录器被调用时,它只是将所有消息记录到一个看似随机的文件中。

我已经搜索了很长一段时间,试图找到解决方案或一些答案,我做错了,但我没有运气。

有没有人知道为什么会发生这种情况?

回答

12

我想我已经解决了这个问题。步骤如下:

  • 在每个线程上创建一个名为LoggerRepository的个人。
  • 设置日志文件名的ThreadContexts属性。
  • 使用XmlConfiguratior配置存储库。
  • 使用LogManager使用该线程的指定LoggerRepository获取指定的记录器(在XML配置文件中)。

作为回报,我得到一个新的配置记录器指向该线程的相应文件。

XML配置是一样的,因为它最初是和这里显示的完整性:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections>  
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 
    </configSections> 
    <log4net> 
    <logger name="ProductionLogger"> 
     <appender-ref ref="XmlAppender"/>  
     <level value="ALL"/> 
    </logger> 
    <appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
     <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
     <immediateFlush value="true"/> 
     <appendToFile value="true" /> 
     <layout type="log4net.Layout.SimpleLayout" /> 
    </appender> 
    </log4net> 
</configuration> 

的代码来创建记录仪如下。每次运行代码时,都会在自己的线程中运行。

ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository"); 
ThreadContext.Properties["LogName"] = logFileName; 
log4net.Config.XmlConfigurator.Configure(loggerRepository); 
ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger"); 

这似乎工作到目前为止没有问题。目前我将继续推进此解决方案,但如果我发现其他问题,我会更新此帖。

+1

非常感谢!我有与线程和登录到不同的文件相同的问题。我通过了很多帖子和解决方案,但只有这一个让我很兴奋。 –

+0

非常感谢你......这种方法解决了我的问题...... – Emerson

4

亚当的答案对我来说效果不错,但我想补充一点。如果您的应用程序中可能重复使用了logFileName,则需要检查以确保该存储库不存在。

string repoName = String.Format("{0}Repository", logFileName); 

// Check for existing repository 
ILoggerRepository[] allRepos = LogManager.GetAllRepositories(); 
ILoggerRepository repo = allRepos.Where(x => x.Name == repoName).FirstOrDefault(); 

// If repository does not exist, create one, set the logfile name, and configure it 
if (repo == null) 
{ 
    repo = LogManager.CreateRepository(repoName); 
    ThreadContext.Properties[KEY_LOG_FILE] = logFileName; 
    log4net.Config.XmlConfigurator.Configure(repo); 
} 

// Set logger 
ILog logger = LogManager.GetLogger(repoName, logName); 
+1

你可以直接调用FirstOrDefault,而不用像这样:'allRepos.FirstOrDefault(x => x.Name == repoName);' –

相关问题