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!