Tuesday, January 11, 2011

Realtime log tracing with log4net using System.Console

I have a project that requires logging information to a text file (and possibly email at a later date).  I decided to look into log4net as I heard many praises about the library.  Within 15 minutes of reading the following tutorial by Tim Corey at CodeProject.com, I was able to start using the tool.  Tim's article is a great "Quick Start" tutorial to get you up and running without fail.
http://www.codeproject.com/KB/dotnet/Log4net_Tutorial.aspx

There was one problem I found while fiddling with the project.  When an error was logged, I needed to find and open the log file to view the error.  What I needed was realtime output of the errors on the console.  Tim, in his article shows how to log to the Output window using a ConsoleAppender, but he does not discuss how to view the errors in a console window for easy and obvious reading (nor does the log4net docs tell you how to do this - not that I found anyway).

I knew that there was a way to redirect output from the Output window (Output/Trace/Debug Window) to the System.Console.  So I had to dust off a book from my bookshelf to come up with the an extremely simple way to provide realtime errors in your console applications.  The code boils down to 2 lines shown here:
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(myWriter);


To make those lines work with log4net, it is required that you set up your app.config with a TraceAppender as follows:

  <log4net>
    <root>
      <level value="DEBUG"/>
      <appender-ref ref="TraceAppender"/>
    </root>
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-5level %logger - %message%newline" />
      </layout>
    </appender>
  </log4net>


That's all there is to getting realtime logging info in you console apps without the need to open log files or query your IDE.  I find it useful for testing libraries that will eventually be included in a windows service. 

Below is some sample code. 
public class TestWritingLogToConsole
    {
        private static readonly log4net.ILog log 
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public TestWritingLogToConsole()
        {
            log.Info("You should see this text in a System.Console window.");
        }
    }
 
    public class Program
    {
        static void Main(string[] args)
        {
            TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
             Debug.Listeners.Add(myWriter);
 
            System.Diagnostics.Trace.WriteLine("Trace Started.");
            TestWritingLogToConsole test = new TestWritingLogToConsole();
            Console.WriteLine("End Program!");
            Console.Read();
            
        }
    }

1 comment:

  1. Preferably, you can use the built-in ConsoleTraceListener which does the same thing basically and is a wrapper around TextWriterTraceListener. Here is the source of that class:

    public class ConsoleTraceListener : TextWriterTraceListener {

    public ConsoleTraceListener() : base (Console.Out) {
    }

    public ConsoleTraceListener(bool useErrorStream) : base (useErrorStream ? Console.Error : Console.Out) {
    }

    public override void Close() {
    // No resources to clean up.
    }
    }

    ReplyDelete