Where I am working now we use Log4Net for our logging, where we usually configure it using
a custom Log4Net> config section in our App.Config something like this.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Temp\SomeLogFile.log" />
<appendToFile value="true" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10485760" />
<rollingStyle value="Size" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="[Header]
"/>
<footer value="[Footer]
"/>
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
</configuration>
Ok this could be done in code, but its just more convenient for me to do this in XML in the config file, so lets assume you too would use a App.Config to configure your installation of Log4Net
Which works fine. You may note that the file elements value is hardcoded to C:\Temp\SomeLogFile.log, which means the logging file
will be stored at “C:\Temp\SomeLogFile.log”. That’s fine.
However the other day we needed to have a dynamically created Log4Net filename
depending on a variable. This variable for us was a command line argument. It took me a little while to figure out how to get Log4Net
to create a filename of my choosing. We even had to delve into how the XmlConfigurator that I would normally use works, such that we could do what it does, but only after we had changed the name of the FileAppender file name. I admit we did have to use a .NET Decompiler to get on our way
The basic idea is as follows (NOTE this is the 1st thing we do before we use the Logger this MUST be done)
- Change the App.Config FileAppender file element value attribute to a string value that will be replaced
- Get the current Log4Net repository, which will will configure later
- Look for all FileAppenders, and grab the file element value attribute to a string value and change it to desired value
- Now tell the current Log4Net repository to configure itself using our in memory modified XML data
This may sound confusing, but its quite ok once you see the code, which is as shown below
App.Config
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Temp\{0}.log" />
<appendToFile value="true" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10485760" />
<rollingStyle value="Size" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="[Header]
"/>
<footer value="[Footer]
"/>
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
</configuration>
Code That is Run 1st Thing
namespace Demo
{
public static class Program
{
private static void ChangeLogFileName(string name)
{
log4net.Repository.ILoggerRepository RootRep;
RootRep = LogManager.GetRepository(Assembly.GetCallingAssembly());
XmlElement section = ConfigurationManager.GetSection("log4net") as XmlElement;
XPathNavigator navigator = section.CreateNavigator();
XPathNodeIterator nodes = navigator.Select("appender/file");
foreach (XPathNavigator appender in nodes)
{
appender.MoveToAttribute("value", string.Empty);
appender.SetValue(string.Format(appender.Value, name));
}
IXmlRepositoryConfigurator xmlCon = RootRep as IXmlRepositoryConfigurator;
xmlCon.Configure(section);
}
[STAThread]
public static void Main(string[] args)
{
ChangeLogFileName("error");
if (args.Length != 1)
{
ChangeLogFileName("error");
PopProcessor.Logger.Error("Error starting invalid command line arguments");
Environment.Exit(-1);
}
ChangeLogFileName(args[0]);
....
....
....
....
....
}
}
}
Hope that helps you out somehow…Enjoy
Oh yes Sacha
That helps me out as I have to add a converting console application to my current project and the ability of being able to log to different files is fantastic news
Thanks
Simon
Cool glad it helped you out
Setting variables in GlobalContext seems to be another popular way, http://stackoverflow.com/questions/562108/log4net-file-names-based-on-globalcontext-properties
Cool thanks for that link. Alternatives are always good