Log Levels in Flash

One of the biggest problems with ActionScript 1.0, as we all know, is the lack of both compile- and run-time validation. Make some small typo, omit a “this”, or get your scoping mixed up inside of a callback, and you’re looking at anywhere from 5 minutes to hours of hunting through your code line by line, if not character by character, trying to figure out why your application is not behaving as expected. One solution is to use ActionScript 2.0, however for those instances when 2.0 is not an option, here are some debugging tips.

First, check out Mike Chamber’s post entitled “Detecting Misspelled Variable Names in ActionScript” which discusses the use of __resolve to trap errors. Second, trace liberally, and use log levels.

I have gotten in the habit of putting a trace at the top of every function, like this:

Foo.prototype.getSomething = function(){trace("Foo.getSomething()");};

If arguments are passed in, I might even trace those out, as well. This kind of tracing, or logging, basically gives you a very detailed trail to follow when debugging your applications. I have even seen people in the Java world log leaving every function as well as entering it. That’s a little extreme for my taste, but I do admit to seeing the value.

The problem is that this level of logging can get very verbose very quickly, and is often much more than you need, especially in the latter stages of building your application when 1) you have a lot of functions and function calls in place, and 2) the app is already working well enough that you usually don’t need to follow its execution function by function. At this point, you usually just want to see specifics, and you don’t want to read through hundreds of traces to find the one piece of output you are looking for.

To handle this issue, I started using “log levels”. Log levels let you control the verbosity of your output, and scale it back or crank it up in order to suite the kind of debugging you need to do. This is a common practice in the Java world, especially with logging packages like log4j. A Flash solution, however, needs to be very lightweight so as not to add unnecessary overhead and increasing file size significantly.

The solution I came up with involves “tagging” all you trace messages with one of two labels: either “verbose” or “debug”. (So far, I have found that using only two log levels is sufficient, however there is no reason you couldn’t use more.) The syntax of my trace statement now look like this:

trace(log("Foo.getSomething()", this.VERBOSE));trace(log("Foo.getSomething(): first arg: " + myArg, this.DEBUG));

The log function is in the logging classes superclass (called “Screen”). Screen contains the following code:

Screen.prototype.DEBUG = 0;Screen.prototype.VERBOSE = 1;Screen.prototype.LOG_LEVEL = this.DEBUG;Screen.prototype.log = function(msg, level){if (this.LOG_LEVEL >= level){return msg;}};

When my LOG_LEVEL variable is set to DEBUG (or 0), I only see “debug” messages, and when it’s set to VERBOSE (or 1), I see both debug and verbose messages. The more “restrictive” or specific the log message, the lower the constant value should be. For instances, if I wanted to add an “info” level, my variables would look like this:

Screen.prototype.INFO = 0;Screen.prototype.DEBUG = 1;Screen.prototype.VERBOSE = 2;

Nesting the call to “log” inside the trace function may seem unnecessarily complicated as opposed to something like this:

Call to log:

log("Foo.getSomething()", this.VERBOSE);

Log implementation:

Screen.prototype.log = function(msg, level){if (this.LOG_LEVEL >= level){trace(msg);}};

The reason I chose to do it the seemingly more complex way is so that I can remove all my debugging statements from my entire application (and all the overhead they create) just by checking the “Omit trace actions” checkbox under Publish Settings. Not only are the trace statements removed, but so is everything contained within them, so the call to log() is gone, as well as the sometimes very long strings being created to send to the log function. The only thing left in the movie is the log function itself, which is small enough to be negligible.

This appears to be an extremely ideal logging solution since it gives you fine-grained control over the quality and amount of logging messages without adding any overhead to production code.

8 Responses to Log Levels in Flash

  1. JesterXL says:

    You didn’t meant to trace your logs in the example above, correct? Since the log function traces it automatically, right? If you did, then you would end up with many blank spaces in your Output. Just making sure I understand.

  2. Flash debugging tips

    Two great articles about useful methods of debugging within flash, they’ll hopefully save me much head-scratching when something doesn’t work as it should… Log Levels in Flash Detecting misspelled variable names in ActionScript…

  3. Sam says:

    I’d be concerned with performance in this level of logging. The advantage of trace statements is that you can omit them in the final compilation. With function calls to log, they’re going to be there in the final solution unless you manually comment them out.That’s two “this” lookups, a function call, and a conditional. Too much processing to do at the top of every function in Flash, IMHO.

  4. Sam, the whole point of this solution is that all the logging code is removed when publishing the movie with the “Omit trace actions” publish setting selected. That’s why the function call to log is inside the trace statement rather than the trace call being inside of the log function. While developing and debugging your application, you can get as many different levels of logging as you want without any performance implications whatsoever in production. This actually works quite well except for the issue that Jesse points out, which is the fact that messages that are not logged because they are beyond the threshold of the current log level product empty lines in the trace panel. I think this solution is still very useful, though, since even with blank lines being printed out, it’s still much easier to see the statements that you are concerned with.

  5. It would be interesting to see a discussion of the mx.services.Log class, and how that can be used for logging (I haven’t looked into it at all).A project I’m working on has a log() function as well, but it traces out to another Flash movie connected via LocalConnection, as well as trace()ing if it happens to be in the IDE. Works well for working with movies that are loaded within other movies on local or remote web sites.

  6. Phillip R. Cargo says:

    I like this ….In many applications you may not be able to use trace() because it will not run within the IDE. This means you may have to use NetDebug.trace().But the NetDebug.trace is not removed when you flip the remove trace() compile switch.But you could modify this idea to simply spit things out via NetDebug.trace(). And both problems are solved!

  7. Ted says:

    Action script is by far the best option

  8. crille says:

    I wonder a thing, do someone know how to make a game with different levels. I know how you sdo it but i want the score to control if you get to another elvel or not, can someone plz help me