Thursday, February 09, 2012
 
 View Article   
24

I needed to be able to change the file log4net was logging on programmatically, on the same time I wanted to use the other configuration options available in the config file.

After several different approaches I ended up with writing a method like the one listed below:

static bool ChangeLogFileName(string AppenderName, string NewFilename)

{

log4net.Repository.ILoggerRepository RootRep;

RootRep = log4net.LogManager.GetRepository();

foreach (log4net.Appender.IAppender iApp in RootRep.GetAppenders())

{

if (iApp.Name.CompareTo(AppenderName) == 0

&& iApp is log4net.Appender.FileAppender)

{

log4net.Appender.FileAppender fApp = (log4net.Appender.FileAppender)iApp;

fApp.File = NewFilename;

fApp.ActivateOptions();

return true; // Appender found and name changed to NewFilename

}

}

return false; // appender not found

}

The method basically search through all appenders to find the appender named in the input parameter. When an appender with the right name is found, it check if the appender is a FileAppender (or to be more precise, that the object found, implement the IFileAppender interface).

I anyone know a more efficient way to find a named appender, I would very much like to know about it.

I found out that using a standard configuration section in the config file failed if the filename was missing, and if a filename was stated that file would be created during the normal configuration (log4net.Config.XmlConfigurator.Configure()), therefore I ended up using the nul device as the filename. My config section is listed below:

<appender name="FileAppender" type="log4net.Appender.FileAppender">

<param name="File" value="nul"/>

<appendToFile value="true"/>

<layout type="log4net.Layout.PatternLayout">

<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>

layout>

appender>

Since the RollingFileAppender inherits the FileAppender, the same method will also work with the RollingFileAppender.

Using the nul device, causes the RollingFileAppender to issue some internal error messages during configuration (you will be able to see they if you turn on internal log4net debug).

A small sidenote on the nul device. The nul device or the “nul” filename has been around in Windows and Dos since the beginning of time, at least since Dos 2.0. I believe it is inherited from the unix operating system. If you try to write to a file named nul, the content you write to the file will simply disappear. You can try it out with Notepad, save a file on c:\nul.txt, you will be warned that the file already exists, but you will be able to save to it. But you will never be able to retrieve anything (WROM Write only memory).

Post Rating

Comments

Dave Murdock
# Dave Murdock
Thursday, February 02, 2006 2:56 PM
I can't thank you enough. You just saved me a ton of time trying to figure this out on my own.

This seems easy once you see it, but if you don't understand the repository concept fully, and the docs were a little opaque to me, you might never figure this out.
____________________________
http://innerexception.blogspot.com
Rick Rigby
# Rick Rigby
Wednesday, July 19, 2006 9:14 PM
Very helpful! Strange that this is not documented & more obvious.
Glitsun Cheeran
# Glitsun Cheeran
Wednesday, October 18, 2006 10:56 AM
The approach is excellent as far as i am concerned.....
It saved a lot of digging the core of log4net
Chris
# Chris
Friday, November 17, 2006 2:22 PM
Awesome!!!! I have been looking for this for the past hour.
Ian Watts
# Ian Watts
Thursday, December 28, 2006 3:14 PM
You are the man! A thousand thank yous!
Max Leifer
# Max Leifer
Monday, August 13, 2007 4:44 PM
Just want to share my approach.

You may define a custom property for your logger (for example in the constructor of your class):
log4net.ThreadContext.Properties["LogFilePath"] = your new path;

Then you can use this property in the configuration file:











Then call
log4net.Config.XmlConfigurator.Configure();
to apply your changes

Note: Do not initialize your logger in the AssemblyInfo.cs.
[assembly: log4net.Config.XmlConfigurator()]

Here is a full snippet:

class Class1
{
private static ILog log = LogManager.GetLogger(typeof(Class1));

///
/// The main entry point for the application.
///

[STAThread]
static void Main(string[] args)

log4net.ThreadContext.Properties["LogFilePath"] = System.Configuration.ConfigurationSettings.AppSettings["NewLogFilePath"];
log4net.Config.XmlConfigurator.Configure();


log.Info("just test");
// ...
// ...

log4net.ThreadContext.Properties["LogFilePath"] = @"..\..\TestingLog\";
log4net.Config.XmlConfigurator.Configure();

log.Info("just new test");


}
}


Max Leifer
# Max Leifer
Monday, August 13, 2007 4:46 PM












Max Leifer
# Max Leifer
Monday, August 13, 2007 4:49 PM
Your appender config can be written as following:
file type="log4net.Util.PatternString" value="%property{LogFilePath}\LOG\"
karthic
# karthic
Friday, August 17, 2007 9:00 AM
really great !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Sreenivas M
# Sreenivas M
Friday, October 05, 2007 5:59 PM
Awesome!
Chandana
# Chandana
Wednesday, January 02, 2008 2:50 PM
Good work budy.......:-), keep on posting...........
Kumz
# Kumz
Tuesday, April 15, 2008 9:28 AM
Can you please share the logic behind why we should'nt initialize the logger in AssemblyInfo.cs?
Jason S.
# Jason S.
Friday, August 15, 2008 7:49 PM
Excellent tip! Thanks for saving me some time!
graham
# graham
Wednesday, October 15, 2008 5:49 AM
Brill guys but which is the better implementation then?
memleaks
# memleaks
Wednesday, December 03, 2008 5:08 AM
Max Leifer's resolution so elegant! thank's alot!
mhm
# mhm
Thursday, May 21, 2009 7:21 PM
This implementation is not thread-safe !! See bellow a simple code that will show you strange things in your log files.

public void run()
{
Thread newThread = new Thread(this.execute);
newThread.Start("a");
newThread = new Thread(this.execute);
newThread.Start("b");
newThread = new Thread(this.execute);
newThread.Start("c");
newThread = new Thread(this.execute);
newThread.Start("d");
newThread = new Thread(this.execute);
newThread.Start("e");
newThread = new Thread(this.execute);
newThread.Start("f");
newThread = new Thread(this.execute);
newThread.Start("g");
}

public void execute(object id)
{

ChangeLogFileName("Appender.Main", (string)id);
log4net.ILog logger = log4net.LogManager.GetLogger("Logger.Main");
logger.Info("just test [" + (string)id + "]");
logger.Info("just new test [" + (string)id + "]");
}

Post Comment

Only registered users may post comments.
Copyright 2005-2008 by FaktNet AS Terms Of Use Privacy Statement