This class is used on several different projects I’m working on. It sends String data to Firebug for it to be displayed in the console. It’s quite useful for live debugging and a good way to see that it wasn’t actually the UI code that’s screwed up, but the data coming in. I love blaming the server guys.
This is a singleton class because I don’t think you’d need more than one. You’re more than free to modify to your liking. Also, by default, it won’t show any traces until the ‘show’ property is set to true.
To use it, do the following:
import com.codemonkeycreative.utils.FirebugLogger; var logger:FirebugLogger = FirebugLogger.getInstance(); logger.show = true; logger.log('This should display in Firebug!');
/** * FirebugLogger.as * * CodeMonkeyCreative.com 2009 * * Author: Michel Boudreau */ package com.codemonkeycreative.utils { import flash.external.ExternalInterface; import flash.utils.getTimer; /** * The logger displays information to the firebug console for easy realtime debugging * * @see flash.external.ExternalInterface * @see flash.utils.getTimer */ public class FirebugLogger { /** String containing the last group name */ private var _groups:Array = new Array(); /** Stores timers needed in the class */ private var _timers:Array = new Array(); /** Debug flag */ private var _show:Boolean = false; /** stores the boundary string for warnings */ private var _warnBoundary:String = "--------------------------------------------------------------"; /** stores the boundary string for errors */ private var _errorBoundary:String = "**************************************************************"; /** saves the prefix for the trace messages */ private var _prefixLog:String = "LOG: "; private var _prefixInfo:String = "INFO: "; private var _prefixDebug:String = "DEBUG: "; private var _prefixWarning:String = "WARNING: "; private var _prefixError:String = "ERROR: "; private var _prefixGroup:String = ""; /** Singleton instance */ static private var _instance:FirebugLogger; /** * FirebugLogger Singleton contructor */ public function FirebugLogger() { // Singleton check if (_instance != null){ throw new Error ("Only one FirebugLogger instance should be instantiated" ); } } /** * Sets a new debug flag value * * @param value:Boolean * @return void */ public function set show(value:Boolean):void { _show = value; } public function get show():Boolean { return _show; } /** * Logs messages without any specific kind of flag. * * <br /><br /> * Usage: {@code "Firebug.getInstance().log('some message')"} * * @param msg:String the message to be logged * @return void */ public function log(msg:String):void { if(_show) { ExternalInterface.call("console.log", getTime() + msg); trace(_prefixGroup + _prefixLog + getTime() + msg); } } /** * Logs messages that gives out information about the current state of the system. * * <br /><br /> * Usage: {@code "Firebug.getInstance().info('some message')"} * * @param msg:String the message to be logged * @return void */ public function info(msg:String):void { if(_show) { ExternalInterface.call("console.info", getTime() + msg); trace(_prefixGroup + _prefixInfo + getTime() + msg); } } /** * Logs messages that displays the value of a variable. * * <br /><br /> * Usage: {@code "Firebug.getInstance().debug(variable)"} * * @param obj:Object the object to be logged * @return void */ public function debug(obj:Object):void { if(_show) { // TODO: better way to show object data ExternalInterface.call("console.debug", getTime() + obj.toString()); trace(_prefixGroup + _prefixDebug + getTime() + obj.toString()); } } /** * Logs messages that needs to notify of a warning in the system. * * <br /><br /> * Usage: {@code "Firebug.getInstance().warn('some message')"} * * @param msg:String the message to be logged * @return void */ public function warn(msg:String):void { if(_show) { ExternalInterface.call("console.warn", getTime() + msg); trace(_prefixGroup + _warnBoundary); trace(_prefixGroup + _prefixWarning + getTime() + msg); trace(_prefixGroup + _warnBoundary); } } /** * Logs messages that needs to notify of a critical error in the system. * * <br /><br /> * Usage: {@code "Firebug.getInstance().error('some message')"} * * @param msg:String the message to be logged * @return void */ public function error(msg:String):void { if(_show) { ExternalInterface.call("console.error", getTime() + msg); trace(_prefixGroup + _errorBoundary); trace(_prefixGroup + _prefixError + getTime() + msg); trace(_prefixGroup + _errorBoundary); } } /** * All group messages are prefixed to show they are in a group. * * <br /><br /> * Usage: {@code "Firebug.getInstance().group('group name')"} * * @param name:String the name of the group to be created * @return void */ public function group(name:String):void { if(_show) { _groups.push(name); setIndentation(_groups.length); ExternalInterface.call("console.group", name); trace(""); trace(_prefixGroup + "[ Start group: " + name + " ]"); } } /** * Ends the message grouping on the last opened group * * <br /><br /> * Usage: {@code "Firebug.getInstance().groupEnd()"} * * @return void */ public function groupEnd():void { if(_show) { ExternalInterface.call("console.groupEnd"); trace(_prefixGroup + "[ End group: " + _groups.pop() + " ]"); trace(""); setIndentation(_groups.length); } } /** * Sets the appropriate indentation to a group * * @param num:int the amount of indentation to be placed * @return void */ private function setIndentation(num:int):void { _prefixGroup = ""; if(num > 0) { var i:int=0; while(i++ < num) { _prefixGroup = "//"; } _prefixGroup = _prefixGroup + " "; } } /** * Creates a timer in an array to be referenced later to check for processing time. * * <br/><br /> * Usage: {@code "Firebug.getInstance().time('timer name')"} * * @param name:String the name to be given to the timer * @return void */ public function time(name:String):void { if(_show) { ExternalInterface.call("console.time", name); trace(_prefixGroup + name +" timer started."); _timers[name] = getTimer(); } } /** * Destroys the timer object and returns the time since its creation * * <br /><br /> * Usage: {@code "Firebug.getInstance().timeEnd('timer name')"} * * @param name:String the name of the timer to be returned * @return int the amount of time taken since the start of the timer in miliseconds */ public function timeEnd(name:String):int { if(_show && _timers[name] != undefined) { ExternalInterface.call("console.timeEnd", name); var timeTaken:Number = getTimer() - _timers[name]; // Gets the time since _timers[name] = undefined; // Destroys the timer trace(_prefixGroup + name +": " +timeTaken+"ms"); return timeTaken; } return -1; // error } /** * Creates a blank line * * @return void */ public function spacer():void { if(_show) { ExternalInterface.call("console.log", " "); trace(""); } } /** * Returns a timestamp string to be used in every log message * * @return String the timestamp string */ private function getTime():String { var timestamp:Date = new Date(); var hour:String = timestamp.getHours().toString(); var minutes:String = timestamp.getMinutes().toString(); var seconds:String = timestamp.getSeconds().toString(); if(hour.length == 1) { hour = '0' + hour; } if(minutes.length == 1) { minutes = '0' + minutes; } if(seconds.length == 1) { seconds = '0' + seconds; } return '['+hour+':'+minutes+':'+seconds+'] '; } /** * Singleton function to return one instance of this class. * * @return FirebugLogger */ static public function getInstance():FirebugLogger { if (_instance == null){ _instance = new FirebugLogger(); } return _instance; } } }



Mike has done an awesome job with this one. I asked (in freenode’s #flex) about using “trace()” too much and he suggested using a logging class. A little bit later he was kind enough to post this code, and help me understand it a bit. Thanks!
This will make a few apps I’m working on much MUCH easier to debug. For Flex novices out there, don’t let the code scare you… it’s super-easy to work with; just save the code to a file at com/codemonkeycreative/utils/FirebugLogger.as then see his usage example above.
Cheers!
keystr0k
PS: We need more people like Mike in the #flex channel! I cannot believe there aren’t ever more than ~80 users in the channel. Arg!
Nice class Michel, but you do know about http://code.google.com/p/flash-thunderbolt/ ?
Which basically does the same thing
Yeah, I do, but I can’t justify such simple functionality to a 50kb+ swc. This is one simple class that’s easy to modify and extremely lightweight.