Reputation: 928
I've tried searching for this in Google and came across this SO question. Although it's partially what I want, the fact that I'm using tasks complicates the issue a bit, as I'll explain.
So, what I am developing is a program to assist first-line users in creating new Active Directory accounts and mailboxes. I have a DataGridView bound to a BindingList which, when the time comes to process the data in the List into new users, is used to create a series of Parallel Tasks which run independently of each other.
What I would like to do is to create one log file per user being created. What I'm trying to do is use common configuration as the basis for the creation of the log file (i.e. same constraints with regards to log level, appender etc...) but use a %property{UserName}
field in the name of the log file so the log messages relating to the different users being created are put into their own distinct log files. That way, if there are issues with the creation of a particular user account, the first-line users (or myself) don't need to dig through one giant log file looking for the problem user.
Using the method described in the above SO question, I was able to create a param in the log4net.config file and by accessing the property using ThreadContext.Properties["UserName"] = entry.Name.ToLower().Replace(" ", "_");
I was able to set the value of the property too! The problem I'm facing is that I can use the property in the conversionPattern for the appender and the username successfully appears, but putting the property in the filename of the appender just causes a file named .\uman_user_tasks_(null).log
to be created. I've tried raising the event in the program's code to force log4net to recognise that the property has changed but this doesn't make a difference.
Additionally, I'm also concerned that since I'm using one ILog object to log the creation of multiple user accounts isn't the right way to go when I'm creating a series of Tasks executing the same piece of code. Can I create a Factory of sorts which uses the appender configuration but appends the username onto the end of the file?
What is the best way to achieve what I'm after? See below for the relevant log4net appender config section if this helps.
<appender name="uman_users" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value=".\log\uman_user_tasks_%property{UserName}.log" />
<param name="UserName" type="log4net.Util.PatternString" value="%property{UserName}" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="2MB" />
<staticLogFileName value="false" />
<preserveLogFileNameExtension value="true" />
<datePattern value="_yyyyMMdd" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date (%method) [%level] (user: %property{UserName}) - %message%newline" />
</layout>
</appender>
Upvotes: 1
Views: 670
Reputation: 928
I managed to come across another SO question which thankfully addressed the issue I was experiencing. As a result, instead of statically referencing a Logger configured in the log4net.config file, I instead used this method for dynamically creating the Appender and Logger objects before registering them in the LogManager.
For anyone interested, I also address memory management by releasing the Appenders bound to these Logger objects after use using the methods described in this post.
Upvotes: 0