Rolling over TextWriterTraceListner logs
Do you utilize the Trace and Debug classes from the System.Diagnostics namespace? Do you use a TextWriterTraceListener to log your messages? Have you ever wondered why the TextWriterTraceListener doesn’t have the ability to roll over its logs at certain intervals?
I’ve developed a number of server-based applications in which we employed the abilities of the System.Diagnostics classes to trace certain application events. Whether its for debugging purposes or to report unexpected events. Its easy enough to utilize the TextWriterTraceListener to capture these messages and easily view them when needed. Depending on what types of events your tracing and at what levels your tracing at (see TraceSwitch), the trace log can get quite large for a server-based application. I would find it very beneficial if the TextWriterTraceListener would roll over its logfile at certain intervals, say on a weekly, daily, or hourly basis. One of my mottos is: If it doesn’t exist, build it!
Here is a simple wrapper for the TextWriterTraceListener that rolls over each day. I’m a little reluctant in posting source code on a blog because I know there are some people who will look at it and say, “Why on earth did you do it that way, you idiot!”. But that’s allright. I can take the criticism. As a matter of fact, that’s why I’m posting this. For one, I want to share this with whomever finds it useful and I also want someone to pick it apart and start a dialogue to discuss if there’s a better solution.
There is one question I hope the blog community can help me come to a conclusion on. What happens when the log file rolls over and another process is trying to write a trace message during the rollover? Does that message get lost? Can I solve it through thread synchronization? Is this even an issue?
Anyhow… here’s the code for the RollOverTextWriter:
using System;
using System.Diagnostics;
using System.IO;
namespace Corgan
{
public class RollOverTextWriter: System.Diagnostics.TraceListener
{
string _fileName;
System.DateTime _currentDate;
System.IO.StreamWriter _traceWriter;
public RollOverTextWriter(string fileName)
{
// Pass in the path of the logfile (ie. C:\Logs\MyAppLog.log)
// The logfile will actually be created with a yyyymmdd format appended to the filename
_fileName = fileName;
_traceWriter = new StreamWriter(generateFilename(), true);
}
public override void Write(string value)
{
checkRollover();
_traceWriter.Write(value);
}
public override void WriteLine(string value)
{
checkRollover();
_traceWriter.WriteLine(value);
}
private string generateFilename()
{
_currentDate = System.DateTime.Today;
return Path.Combine(Path.GetDirectoryName(_fileName),
Path.GetFileNameWithoutExtension(_fileName) + “_” +
_currentDate.ToString(“yyyymmdd”) + Path.GetExtension(_fileName));
}
private void checkRollover()
{
// If the date has changed, close the current stream and create a new file for today’s date
if (_currentDate.CompareTo(System.DateTime.Today) != 0)
{
_traceWriter.Close();
_traceWriter = new StreamWriter(generateFilename(), true);
}
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
_traceWriter.Close();
}
}
}
}
