30/04/2013
by Stephan Partzsch
2 Comments

Tracking of client errors in ActionScript

Probably everybody is familiar with errors in Adobe Flash. Most of us are faced with them while coding software or while fixing bugs that have been reported e.g. via a bug tracking system.
A good practise is to use custom error types inside your code. This allows to identify your own errors better and more independent from other frameworks. Most unit test frameworks like FlexUnit support or even require custom error types.
With Flash Player 10.1 or AIR 2 comes the global error handling. This works very straight forward and every Error or ErrorEvent which is not handled by try…catch blocks or appropriate error event listeners, is received as an UncaughtErrorEvent object.

package
{
    import flash.display.Sprite;
    import flash.events.ErrorEvent;
    import flash.events.MouseEvent;
    import flash.events.UncaughtErrorEvent;

    public class UncaughtErrorEventExample extends Sprite
    {
        public function UncaughtErrorEventExample()
        {
            loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, handleUncaughtError );
        }
        
        private function handleUncaughtError( event : UncaughtErrorEvent ):void
        {
            if ( event.error is Error )
            {
                // handle the error
            }
            else if ( event.error is ErrorEvent )
            {
                // handle the error event
            }
            else
            {
                // a non-Error, non-ErrorEvent type was thrown and uncaught
		// ???
            }
        }
    }
}

Usage of global error handling in ActionScript

With this you have a central point where all your error can be handled without missing a single one. That’s cool, isn’t it?
But, what will you do if you receive an error that you can not handle in a senseful way? Or an error occurs only now and then and you can not figure out when and why? Of course, you can log the error information, which is helpful while working on a local machine and works best for all the bugs/errors you can reproduce.
If you want to get notified about errors if your application is running on remote clients, you will need something different.
One way could be to send the error information to your own backend where they will be stored. The drawback of this solution is that this system produces additional work and requires some maintenance over time.
Therefore I asked myself if there is a remote error logging system usable with ActionScript like they exist for mobile devices programming. Unfortunately I couldn’t find anything good that can be used out of the box (if you know one, please put a note in the comments). After some further searching Airbrake popped up and seemed the right tool to collect error data.

Airbrake error tracking service

Airbrake (source: https://airbrake.io/pages/home)

Airbrake supports Ruby on Rails and iOS directly and comes with third party integrations for PHP, .Net, Java. But again, there is no ActionScript support. Luckily Airbrake offers a RESTful XML API called Notifier API which is used by other third party developers already. Therefore I gave it a try too and came up with my own integration called ‘as3-airbrake-notifier’, which can be found on github.
The functionality it is very simple structured and composes the given error data into an XML according to Airbrakes XSD. Thanks to Peter Hoeches parser it is not required to parse the stack trace beforehand, because it brings the ActionScript stack trace in the right format automatically.
The usage of the notifier is quite simple as well, although a lot of information can be added. See how it works:

First, the notifier has to be initialized like this:

airbrakeNotifier = new AirbrakeNotifier( "APP_KEY", AirbrakeNotifier.ENVIRONMENT_TESTING, "APP_VERSION", "HOST_NAME", "PROJECT_ROOT" );

airbrakeNotifier.addEventListener( Event.COMPLETE, handleSendAirbrakeNotificationComplete );			
airbrakeNotifier.addEventListener( HTTPStatusEvent.HTTP_STATUS, handleAirbrakeNotificationHttpStatus );			
airbrakeNotifier.addEventListener( IOErrorEvent.IO_ERROR, handleAirbrakeNotificationIoError );

Everything except the APP_KEY which can be found on the Airbrake account website can be omitted. This data is only for convenience. The second parameter defines the environment in which the application is running. Predefinitions from as3-airbrake-notifier (“testing”, “staging”, “production”) can be used or a custom string can be defined. The last parameter can be used to track the path to the project in which the error occurred.

As the second and already last step the error data is send like this:

airbrakeNotifier.createCrashReport( error.errorID, error.name, error.message, StackTraceParser.parseStackTrace( error.getStackTrace() ) );
airbrakeNotifier.addRequestInformationsToCrashReport( "requestUrl", "component", "action", requestParams, sessionParams, environmentVars );
airbrakeNotifier.sendCrashReport(); 

A crash report is created that contains all the information that come with the ActionScript Error or ErrorEvent object. These are passed into the first function. Optionally more information can be added, e.g. if the error occurred during an HTTP request or something similar. This is recommendable because therefore the source of the error can be easier identified.
The first parameters are strings and define the requested url, the component of the requesting application as well as the name of the action (can be omitted if no special action was in use) in which the error occurred. The last three parameters are optional dictionaries and are supposed to contain information about the parameters of the request itself, the current session and basic information about the application or the environment. Airbrake describes the last bunch of information as CGI variables (e.g. SERVER_NAME). Do not feel confused by the naming of the last parameter, you can use every kind of information you want and you will find it in Airbrake without problems.

Global error handling is key to detect all your errors. And an error logging system like Airbrake helps to have a look into data of client errors. Therewith you are able to quickly respond to bigger problems, especially regarding remote calls in live mode. Furthermore you will detect parts of wrong implementation as well as edge cases of your functionality a lot earlier.
However there are drawbacks too. Most significant are the costs for using Airbrake which are based on the number of errors that can be detected. If you want to catch all, it will be expensive. If the user has no debug player installed, you won’t get any stack trace and in this case the information to understand the error is very sparse. But if Flash Player 11.5 or bigger is used, the stack traces are also available in the non-debugger version.
The second drawback relates multi-version software, where Airbrake is lacking of a reset button for errors. The number of occurrences of an error is counted since it was detected for the first time. This count can not be reset (e.g. if a new version is deployed) and therefore you won’t know how often this error occurred for your latest version. In my eyes this isn’t a benefit and the major drawback of Airbrake.

SUMMARY

Basically it is a nailing idea to catch and process/detect all of the errors in a Flash client application. Problems can be quickly detected and resolved. Airbrake is a good fit but if you have a huge user base and only a small budget then Airbrake is probably not the best solution. One alternative is the open source version of Airbrake called errbit that you can run on your own server. Luckily it comes with the missing reset button and the as3-airbrake-notifier library will work with this as well.

30/04/2013
by Stephan Partzsch
0 comments

Hello World (out there)

I would like to welcome you to the very beginning of my brand new blog :)
It should grow over time to get not only a helpful reference work but also a source of inspiration.
If you want you can have a look for new posts every now and then. Or use the rss feeds which are available for topics regarding coding, photography or for all topics together. And now… Enjoy!