Logging to an individual log file for each individual thread
I think I have worked out the issue. The steps follow:
- Create an an individual
ILoggerRepository
object (loggerRepository
in this example) on each thread. - Set the ThreadContexts property for the log file name.
- Use the XmlConfiguratior to configure the repository.
- Use the LogManager to Get the named logger (in the XML configuration file) using the named LoggerRepository for that thread.
In return I get a new configured logger pointing to the respective file for that thread.
The XML configuration is the same as it was originally and shown here for completeness:
<?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>
The code to create the loggers is below. Each time this code is run it is run in its own thread.
ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository");
ThreadContext.Properties["LogName"] = logFileName;
log4net.Config.XmlConfigurator.Configure(loggerRepository);
ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger");
This seems to work with no issues so far. I will be moving forward with this solution for the moment but I will update this post if I find out anything else.
Adam's answer has worked pretty well for me, but there is one this I would like to add. If there is a possibility of your logFileName being reused in your application, you will need to check to make sure the repository does not already exist.
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);