Windows Phone 7 Pitfall: The Dispatcher and Deactivation Windows Phone 7 Exam E-Book available

Fixing NLog's Logging to a Web Service

Published on Tuesday, October 18, 2011 5:24:52 AM UTC in Programming

Logging and Tracing on the phone is somewhat limited because your options of logging targets are. Popular targets like databases or the event log are not available at all or only work in the emulator (console), and others like log files are rather inconvenient, because your only option is to write to isolated storage. Luckily, all common logging frameworks offer additional options that can be used from Windows Phone too, in particular remote targets like writing to a web service. NLog introduced experimental support for Windows Phone back in January and finally included it in the official 2.0 release in July. Unfortunately, an important feature of logging to a web service is broken. Here is how to fix that.

The problem

A tutorial that shows how to easily set up NLog on Windows Phone 7 is available here. It uses a WCF service as target for the logging that simply "tunnels" the messages from the phone to whatever logging targets you have defined there. This not only allows you to log messages originating from your phone application, but for example to aggregate logging from other sources as well, like a service your phone application uses – a nice option to analyze the interaction of distributed components.

Step 6 of the above linked tutorial shows how to add parameters to your phone side logging that are included in every log message automatically. This is an important feature that lets you change the information that is logged through configuration on the fly, without altering all the places you log at manually. Examples for this are to catch the current thread Id or a client time stamp that is then sent along to the logging service as parameter.

<parameter name="t" layout="${threadid}" />

The service can use that parameter in its own configuration to include the value in the actual logging output, like:

<target name="console"
        xsi:type="Console" 
        layout="${message} (thread: ${event-context:t})" />

The problem with that is that it's simply not working. If you're familiar with how thread ids look like you can even see in the tutorial that something's not quite right there. And if you add more than one parameter you'll start to see seemingly random numbers and pipe characters as values for parameters.

And a solution

The reason for this is that the built-in LogReceiverForwardingService parses the passed parameters incorrectly. Luckily the implementation of that service is rather trivial, so after I finally found out what's wrong (took me a while), I was quickly able to fix the parameter handling there. Until a fix is released or included with NLog, you can use my solution provided here:

CustomLogReceiverForwardingService.zip

Simply extract the file and include it in your (logging) project. It's basically the code of the original implementation without the bug. You can then use this service instead of the original one in the exact same way. For what is shown in the tutorial (which uses a console application), this would be:

var uri = new Uri("http://localhost:5000/LogReceiver.svc");
// use the fixed service implementation
var host = new ServiceHost(typeof(CustomLogReceiverForwardingService), uri);
var binding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(ILogReceiverServer), binding, uri);
host.Open();
Console.WriteLine("Host opened.");
Console.ReadLine();
host.Close();
Console.WriteLine("Host closed.");

And that's it. Passing parameters from the phone and other sources to your logging service now works correctly.

I created a work item in Codeplex's issue tracker here, in case you want to track its state.

Tags: NLog · WCF · Windows Phone 7