Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Creating a real-time Trace listener with WCF

3.21/5 (10 votes)
17 Feb 2008CPOL2 min read 5   595  
Instead of reading trace messages in a file, get them in a WPF app real-time via WCF.

Introduction

This is a trace listener that can be used over a network. I.e., if you have trace messages being written in your application and want to listen to them over the network, you can add a DLL in the bin directory of the app, add a few lines in the config file, and you are ready to listen remotely.

Background

I searched for some similar articles and the above one was close, but needed inclusion into the project being developed. I wanted to be able to have a pristine production service running without anything attached to it in the way of debugging and then, if needed, drop in a DLL and a few config entries and be able to listen to it.

Because of this, I'm not terribly worried about performance. That being said, I used OneWay WCF attributes so it doesn't wait for a response when writing each trace, it just dumps the message and continues.

Using the code

The good news is that in order to use it, you only need code similar to the below in your config file:

XML
<system.diagnostics>
 <trace autoflush="true" indentsize="4">
  <listeners>
   <add name="NetworkTraceListener" 
     type="NetworkTraceListener.TraceClient, NetworkTraceListener"/>
  </listeners>
 </trace>
</system.diagnostics>

<!--WCF config for NetworkTraceListener, pointing to viewer-->
<system.serviceModel>
 <client>
   <endpoint 
      address="net.tcp://localhost:8001/NetworkTraceListenerViewer/service" 
      binding="netTcpBinding" contract="ITraceServer" />
 </client>
</system.serviceModel>

Points of interest

You'll need NUnit 4.0 to compile the solution - or remove the test project. To use, launch the WPF app which is the viewer and server, and then include the above and the compiled NetworkTraceListener.dll in the project you want to listen to. You should see the messages in the viewer application.

I used a static Start and Stop method on TraceServer rather than an instance. This was for convenience to get this thing going quickly. If I used an instance class, I would need some way of getting the events from the WCF instance to the separate instance used to start/stop. I didn't foresee needing multiple viewers in the same process, so it seemed the simple way to go.

The TraceClient does something unusual, in that it eats all exceptions. I didn't ever want a communication failure, listener being closed, etc. to cause an app to fail when all I wanted to do was listen to the trace messages. I didn't bother logging those issues because I'm not interested in them and because trying to do additional writing in a Trace listener has caused me some problems in the past.

WCF was very easy to use - I was very happy with how simple it was to setup network functionality without too much wrangling with ports and sockets and what not.

Here is the unit test which confirms that a server can be instantiated, a client can write a couple messages, and they are received:

C#
[Test]
public void TestSingleStartStopWithSendOk()
{
    int MessageCount = 0;
    try
    {
        AutoResetEvent ServerStartWait = new AutoResetEvent(false);
        
        TraceServer.ServiceListening += 
          new TraceServer.ServiceListeningType(delegate(object o, EventArgs e) {
            ServerStartWait.Set();
        });

        TraceServer.Start();
        TraceServer.MessageReceived += 
          new TraceServer.MessageReceivedType(delegate (string Message) {
            MessageCount++;
        });

        //wait for server to start w/ timeout of 20 seconds
        ServerStartWait.WaitOne(20000, true);

        TraceClient client = new TraceClient();
        client.WriteLine("test1");
        client.WriteLine("test2");
        client.Flush();


        //allow time for messages to be sent before forcing connection closed
        Thread.Sleep(1000); 
        client.Close();
    }
    finally
    {
        TraceServer.Stop();
    }
    Assert.AreEqual(2, MessageCount);
}

ToDo

Add a "gratuitous animation" checkbox which enables Star Wars style scrolling trace messages as received. Possible "gratuitous audio" checkbox with theme music.

History

  • 17-Feb-2008 - Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)