记录每个单独线程的单个日志文件
我有一个服务应用程序,它在启动时读取XML文件并为XML文件中的每个条目启动一个线程。 每个线程都创建一个worker类的实例,该实例需要记录器将任何输出记录到特定于线程的日志文件中。
在服务app.config中,我将log4net配置设置设置为使用XML appender,并将文件指定为PatternString,如下所示:
在创建的worker类的每个实例的线程锁定方法中,我使用log4net.LogManager.GetLogger("MyLogger")
方法获取记录器,然后使用ThreadContext.Properties["LogName"] = "Log name prefix"
设置当前线程PatternStrings LogName属性ThreadContext.Properties["LogName"] = "Log name prefix"
。
所有文件都已创建,但是当调用记录器时,它只会将所有消息记录到一个看似随机的文件中。
我已经搜索了很长一段时间试图找到一个解决方案或一些我做错的答案,但我没有运气。
有谁知道为什么会这样?
我想我已经解决了这个问题。 步骤如下:
- 在每个线程上创建一个名为LoggerRepository的个体。
- 为日志文件名设置ThreadContexts属性。
- 使用XmlConfiguratior配置存储库。
- 使用LogManager使用该线程的命名LoggerRepository获取指定的记录器(在XML配置文件中)。
作为回报,我得到一个新配置的记录器,指向该线程的相应文件。
XML配置与最初的配置相同,并在此处显示为完整性:
创建记录器的代码如下。 每次运行此代码时,它都在自己的线程中运行。
ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository"); ThreadContext.Properties["LogName"] = logFileName; log4net.Config.XmlConfigurator.Configure(loggerRepository); ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger");
到目前为止,这似乎没有任何问题。 我现在将推进此解决方案,但如果我发现其他任何内容,我会更新此帖。
亚当的答案对我来说效果很好,但我想补充一点。 如果您的应用程序中可能会重用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);