Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

A logging utility with a Forms based console

4.50/5 (2 votes)
12 Sep 20063 min read 1   512  
A logging utility with a Forms based console.

Sample screenshot

Introduction

When I first started using Visual Studio, I was disappointed that Trace output goes into a standard text window within the IDE. What I needed was a record oriented logging system with output to a graphical console. My solution was a fairly simple solution based on .NET remoting and Windows .NET Forms.

The Console

The console simply presents a list of logging messages received by a client. You can apply sorts on the columns. New messages will be placed at the top of the list.

There is no absolute guarantee that the messages will show up in the exact same order that they were sent. This is because I am using the default thread pool with .NET remoting. So, even though the messages will be sent in order, the console may not execute the messages in the order received. It appears, though, that this is a very rare situation. Most of the time, the console will show the message in the correct order. Regardless of message execution ordering, the timestamps on entries will always reflect the time the message was sent.

You can drill down on individual messages on the console by double clicking a row. You will get something like this:

Sample screenshot

The Console Configuration

The application configuration file should read as follows:

XML
<?xml version="1.0" encoding="utf-8" ?>
 <configuration>
  <appSettings>
   <add key="port" value="1439"/>
  </appSettings>
 </configuration>

You will also want to make sure that the firewall allows this port to be opened. You can use any port you wish. You will just have to make sure that the port specified in the client config file is the same.

The Client API

The API is fairly simple. First, add a references to the logger_client.dll from the logger project.

Second, add a reference within your code:

C#
using LiveSwitch.LoggerClient;

Next, instantiate a Logger proxy. These are lightweight objects, so they don't have to be disposed. You can create as many as necessary without wasting heavyweight resources.

C#
Logger logger = new Logger("component name");

The logger class has six relevant methods:

  • logger.Debug("text");
  • logger.Info("text");
  • logger.Warning("text");
  • logger.Warning("text", exception);
  • logger.Error("text");
  • logger.Error("text", exception);

Client Configuration

The client application requires an application setting in its configuration file. Note that you cannot use application properties, since the dependent client DLL needs to read the executable's config file, and it does not have access to the code generated by the IDE.

An application's properties are provided in a file named <exe file name>.config.

Here is an example:

XML
<?xml version="1.0" encoding="utf-8" ?>
 <configuration>
  <appSettings>
   <add key="loggerUrl" value="tcp://localhost:1439/logger"/>
  </appSettings>
 </configuration>

Internals

Messages are batched on the client library side and sent by a single worker thread. The following is the main loop, shared by all client logger instances, used to ship batches of requests to the logger application.

C#
private void Start()
{
    while (true)
    {
        ILogger.LogMessage[] msgs;
        lock (this) 
        {
            while (_list.Count == 0)
            {
                Monitor.Wait(this);
            }
            msgs = _list.ToArray();
            _list.Clear();
        }
        _client.Log(msgs); // xmit the batch of messages
    }
}

As you can see, the logger client library background thread uses monitor locks to synchronize with the application.

Here, you can see the application's info logger notifying the background thread that data is ready.

C#
internal void LogInfo(string comp, string data)
{
    ILogger.LogMessage msg =
        new ILogger.LogMessage(ILogger.LogMessageType.INFO, 
                               data, comp, DateTime.Now, _host, null);
    lock (this)
    {
        _list.Add(msg);
        Monitor.Pulse(this);
    }
}

As you can see, the interaction is very textbook.

Conclusion

This logging system has been extremely helpful while developing applications. I hope some of you will find it useful.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here