Tuesday, February 3, 2009

Log4Net - Configure at Runtime to Log to Textfile

I spent a few minutes hacking at log4net today. It's been a very long time since I used it and i've always used it along with an app.config. Today however, I attempted to use it for other purposes that required specifying the log4net configuration parameters at runtime so that output could be directed to a text file. I'm not a log4net expert, nor do I claim any expertise in this area. That being said, this seemed to work for me.

I created a FileStream and TextWriter to start things off. The LOGFILEPATH is a string that indicates the full path to where the log file will be stored:

FileStream filestream = new FileStream(LOGFILEPATH, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
System.IO.TextWriter textwriter= new StreamWriter(filestream);
Next, I looked into the PatternLayout class for an example pattern to use for log output. I found a good reference online here.

log4net.Layout.PatternLayout patternlayout = new log4net.Layout.PatternLayout();
pattern.ConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline";

I then created an associated TextWriterAppender. This is where we will associate the TextWriter and PatternaLayout together into a bundle. I also set the ImmediateFlush option to true.

log4net.Appender.TextWriterAppender textwriterappender = new log4net.Appender.TextWriterAppender();
textwriterappender.Writer = textwriter;
textwriterappender.Layout = patternlayout ;
textwriterappender.ImmediateFlush = true;

Unfortunately for me, I first started this endeavor by creating my own Appender... which wasn't too bad but after browsing through the source tree and checking out src\Appender, I figured i'd just use theirs. So I did ! To finish it all up, I simply initialized the BasicConfigurator with the created textwriterappender.

log4net.Config.BasicConfigurator.Configure(textwriterappender);
I also needed to set the debug level. After some mild google-ing, I did this:

((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root.Level = log4net.Core.Level.Debug;
So, there you have it. After this, you simply use log4net as you normally would in your code. For me, it was as simple as:

log4net.ILog log = log4net.LogManager.GetLogger(typof(MYCLASS));

Where, MYCLASS is the class I was interested in logging. I'm not sure if this is the correct way to go about doing this but it appeared to work for me. I'll need to spend a bit more time reading through the source and learning the 'right way' around the library. It's interesting to note that within log4net-1.2.10/src/Appender, there are several other types of Appender classes defined for use, including AdoNet, Console, Telnet, Udp, etc.... Good to know in case you ever are interested in heading down that road.

If you know of a better way to perform this type of runtime configuration, please let me know. If not, hopefully this works for you!

Cheers!

No comments: