Friday 21 June 2013

Logging with AppHarbor Web & Background Workers

Last year AppHarbor introduced Background Workers into their repertoire. You can push a .net solution with a console application project that will be compiled and executed just as you would expect if executing the task locally. You can have a Background Worker and a Web Worker in the same application. The Background Worker will have the same access and to the adds-on used by the Web Worker so you can delegate any 'offline' processes to a Background Worker to allow your web app to concentrate on just serving responses. This provides a good platform for horizontal scaling.

A source of frustration with this approach however is logging. The standard AH add-on for logging is LogEntries. LogEntries is a generic SAAS consumed by many integrated hosting providers. It provides token-based TCP logging when used as another target or appender with NLog or Log4Net respectively. Logs are collected with almost zero latency and are visible in the snappy LogEntries interface.

The frustration arises when you are using LogEntries with the Web Worker + Background Worker architecture I described. As I mentioned, LogEntries by default is token-based, meaning your application gets one token to use to identify itself. This token is shared by the Web Worker and the Background Worker.

If your Background Worker (running your Console Application) and your Web Worker (running your Web Application) are dependent on shared domain projects - meaning that they both make consume the same classes - then your logs can be ambiguous as to the source of the calling code. Has your 'FATAL' entry been encountered in the Web Worker or the Background Worker? You cannot tell by the type alone!

Thankfully, LogEntries provides a neat way of solving this issue, though it is not obvious if you are starting with the AppHarbor add-on, as the configuration is performed behind the scenes - you're fast-forwarded through the basic introduction. LogEntries' Logs live under a default Host, the AppHarbor Host, which is added upon Initialisation. A Default Log is added to the AppHarbor Host, and this is where your logs end up when using the provided token. The token is automatically injected into your web/app.config settings when the Web Worker and Background Workers are deployed.

To make our Web Worker and Background Worker write to separate Logs, we simply have to add a new one in our AppHarbor Host. Make sure that you select Token TCP transport.






In doing so we get a new token. We can then use that token in the Console Application app.config, so that all logging is directed to the Background Worker log. The configuration of the app.config le_appender in Log4Net looks like the following:

  <log4net>
    <appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LeLog4net">
      <Token value="some-thing-secret" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%level% %logger %m" />
      </layout>
    </appender>
    <root>
      <appender-ref ref="LeAppender" />
    </root>
  </log4net>

This forces the LeAppender to use the token you have provided - and not the default LOGENTRIES_TOKEN injected by AppHarbor into your app.config. Separate logs are yours!


Thursday 6 June 2013

Implement a C# Interface in F#

Whilst seeking ways to learn F# and weave it into predominantly C# projects I have started to implement interfaces written in C# with an F# version. That sometimes means re-writing a C# implementation with an F# implementation. It works particularly well for a number of reasons:

Motivation - Provides direction rather than just 'hacking about' with the language.

Confidence - If you have test coverage, you can use the same tests to be sure your code is working.

Syntax - Provides a sound introduction to the indentation and parenthesis use in F# by forcing you to translate your own C# code.

Insight - Helps to reinforce that F# still compiles to IL underneath and is executed on the CLR - its all .NET after all!

Communication - Helps others to learn by examining the 'before' (C#) and 'after' (F#) implementations.

Seamless - Integrates with your existing C# solution when using dependency injection and IoC maintaining your decoupled architecture.

In F#, interfaces are implemented Explicitly as opposed to Implicitly in C#. This means that we must provide pointers to the functions we wish to fulfil the interface per method or property. The Gist below provides examples of the various signatures we would expect to implement.