Home >
Client-side Error Logging Architecture
In one of my previous articles I spoke about the need for client-side error logging. In that article I elaborate a bit on why you need to. Here I explain one way to go about doing it.
The core logic is that client-side code calls out to the server-side passing some parameters to it. The server-side logs those values and makes them available via a report.
In the solution I architected in my diagram below I chose to use a cache server that we have already in place that monitors and handles HTTP requests. I also chose to utilize an existing reporting suite that our Operations department uses. So the only server-side code that we needed to write was a Ruby (at first, then later converted to Perl because that's what was already installed on the production box) script to pull down the logs from where the cache server left them, parse them up and feed them to the reporting agent in a format that it was comfortable with.
Your implementation could just as easily replace the cache server piece with custom server-side code or a web service.
For my client-side implementation, initially I was concerned with tracking errors and heart-beats in our video player, which is all AS3, so I created an ActionScript class to encapsulate all of the needed functionality. I made it a singleton so I could subclass it for additional implementations.
import flash.display.Loader;
import flash.events.IOErrorEvent;
import flash.external.ExternalInterface;
import flash.net.URLRequest;
public class MessageLogger
{
private var loggingURL:String;
private const DEFAULT_LOG_URL:String = [your server-side script];
private static var _instance:MessageLogger = null;
private var errMsg:String
private var errSrc:String
private var loader:Loader
public function MessageLogger(src:String)
{
errSrc = src
}
public static function getInstance(src:String):MessageLogger
{
if(_instance==null){
_instance = new MessageLogger(src);
}
return _instance;
}
private function assembleURL():void
{
loggingURL = DEFAULT_LOG_URL + errSrc + "&errMsg="+errMsg + "&url="
try{
loggingURL+=ExternalInterface.call('window.location.href.toString');
}catch(e:*){}
}
private function onIOError(e:IOErrorEvent):void
{
}
public function logMessage(msg:String):void
{
errMsg = msg
assembleURL()
loader = new Loader();
loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, onIOError)
try
{
loader.load(new URLRequest(loggingURL))
}catch (e:Error){}
}
}
MessageLogger.getInstance([class name]).logMessage([Error message]);
And this is completely flexible, in fact we just used this architecture, with the addition of a JavaScript wrapper class, to track all of our interactions with Amazon Web Services.




Facebook Application Development
Last night I just achieved to do the same, but it send the log to a textarea, and to the trace, and to the server, you can tune the behaviour. I have achieved multilevel of log message from silent (no message) to simple trace bug error, or full verbose and warning.
to avoid to copy and paste the name of class like that :
MessageLogger.getInstance([class name]).logMessage([Error message]);
I have whrite this
protected function whrite(str:String, object:*=null):void
{
if(m_silent == false)
{
if(object != null)
{
var className:String = flash.utils.getQualifiedClassName(object);
}
m_trace(m_prefix +className+"() " + m_br + m_prefix+ "\t" + str + m_br);
}
}
_________________________________________________
Notice the "flash.utils.getQualifiedClassName(object);"
I have a question to you :
What happen if someone whrite this : obj:MessageLogger = new MessageLogger()
I think you get a new instance of your "singleton"
to avoid that you can add this code :
public function Debug()
{
if(s_instance != null)
{
var error:String = "failed use getInstance instead";
trace(error);
throw new Error(error);
}
m_debugAbstract = new DebugAbstract();
m_viewDebug = new AioViewDebug();
}
I have never publish open source code, but If I have time I will look for a permissive licence to publish it. If you have some idea of what kind of licence I can use fill free to advice .
thx for your post.
Last night I just achieved to do the same, but it send the log to a textarea, and to the trace, and to the server, you can tune the behaviour. I have achieved multilevel of log message from silent (no message) to simple trace bug error, or full verbose and warning.
to avoid to copy and paste the name of class like that :
MessageLogger.getInstance([class name]).logMessage([Error message]);
I have whrite this
protected function whrite(str:String, object:*=null):void
{
if(m_silent == false)
{
if(object != null)
{
var className:String = flash.utils.getQualifiedClassName(object);
}
m_trace(m_prefix +className+"() " + m_br + m_prefix+ "\t" + str + m_br);
}
}
_________________________________________________
Notice the "flash.utils.getQualifiedClassName(object);"
I have a question to you :
What happen if someone whrite this : obj:MessageLogger = new MessageLogger()
I think you get a new instance of your "singleton"
to avoid that you can add this code :
public function Debug()
{
if(s_instance != null)
{
var error:String = "failed use getInstance instead";
trace(error);
throw new Error(error);
}
m_debugAbstract = new DebugAbstract();
m_viewDebug = new AioViewDebug();
}
I have never publish open source code, but If I have time I will look for a permissive licence to publish it. If you have some idea of what kind of licence I can use fill free to advice .
thx for your post.
@damien - that looks good. Unfortunately with AS3 we have to fake singletons much like we fake abstract classes. Half the time I start out making abstracts with good intentions, but end up instantiating them and then just renaming them - see my Calendar posts for an example of that.
And when I open source a project I usually use google's project hosting http://code.google.com/projecthosting/ - it gives you a choice of licenses and easy svn checkout.
thanks
I know google code, I will just carrefully read the licences to choose one of thems, maybe a MIT or BSD.
I come from C++ and It's true, it's boring to not have abstract class, and polymorphism. It push me to use composition or interface. I will have a look to your Calendar to increase my skills in AS3.
check this out, I will give you an access if you want to add the HTTP fonctionality.
I have choose the MIT licence quit permissive.
http://code.google.com/p/flex-debug-system/source/checkout
[...] Having your app keep a detailed log can be indispensable for figuring out tricky user-reported bugs. This is easy on the server-side, where you can use any logging framework or just write to a file. Flash includes the trace function, which is useful while developing, but nearly impossible to get from an end-user. Flex, however, has a good logging api that lets you put log statements anywhere you want. I’ve always wanted the interface to be as easy as trace, so I write a couple of scripts to make it easier. [...]
Flex is nice, but I've found most serious shops are making their own framework as a flex substitute, in pure as3. Reason being, with Flex it's all or nothing, and with everything it's way too heavy. You make your own framework and include pieces of it as you need it. My solution is pure AS3.
@sean - great site, by the way, a lot of interesting articles
@Tom barker : AS3 is relativly young, comparing to C++ wich provide several good librairies like MFC QT WXwidget GTK. I risk to compare flex to MFC, because it's sometimes heavy to get some features you have natively with C++ lib. for exemple MFC handle very poor event system. Slot provide Signal Slot implementation a really helpfull functionnality. I had hope have some signal slot like QT. So it's not so creasy idea to use or developp or start to developp a new UI framework for AS3, if it fix some lack. For moment I happy to use a ready to use kind of blackBox it increase time to market.
However, flex is based on long experiencies of UI framework, and not so bad at all, mxml description, css and so on...
@client-side... :
After 3 month developping in as3/flex maybe I should have read the doc entierly :) (may be)
@damien - I think that's a fair comparison. I do like Flex, it's definitely fun to work with, it's just when you're watching your kb and trying to fit your content within the maximum IP packet size, if possible, for minimum round trips to load your page, it's just not always the best solution.