Logging Flex 2 and AS 3 apps with Firebug and ThunderBolt

Posted on April 21, 2007

A few weeks ago Martin Kleppe started a project on Google Code called Flash-ThunderBolt. The idea behind based on Manfred Webers blog entry "Make MTASC talk to Firebug" which describes a way for logging Flash apps compiled with MTASC using Firebug.

I've already joined the Flash-Thunderbolt project for coding an AS3 version. It won't be a copy of the current AS2 package but rather another approach for using Firebugs Console API as simple as possible. Check it out, here are my first steps:

Example

To see this content latest Flash Player Plugin is required.

Instructions

The ThunderBolt AS3 package contains only one class named Logger.as. It supports logging primitive types such as Number, String, Boolean, etc. as well as Objects, Arrays and public properties of all classes. Use short cuts for determing different log levels as Zeroi does: "i" = info, "e" = error, "w" = warn, "d" = debug.

Here is an example:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
 3  <mx:Script>
 4      <![CDATA[
 5          import org.osflash.thunderbolt.Logger;
 6          import flash.events.Event;
 7          private function traceToFirebug(event:Event):void
 8          {
 9              var n: int = 5;
10              var s: String = "Lorem ipsum";
11              var o: Object = {exampleArray: ["firstValue", "secondValue"], y: 10, exampleString: "Hello", nestedObject: {x: 100, y: 200}};
12              var a: Array = ["firstValue",{x: 100, y: 200}, "secondValue"];
13              var label: String = event.target.label;
14              switch (label)
15              {
16                  case "info":
17                      Logger.trace ("i a simple string", s);
18                  break;
19                  case "error":
20                      Logger.trace ("i a number typed as int", n);
21                  break;
22                  case "warn":
23                      Logger.trace ("e an array with a nested object: ", a);
24                  break;
25                  case "debug":
26                      Logger.trace ("w an object with a nested object and nested array",o);
27                  break;
28                  default:
29              }
30          }
31    ]]>
32  </mx:Script>
33  <mx:Style source="css/logger.css"/>
34  <mx:Text htmlText="Press F12 to open Firebug" paddingBottom="20"/>
35  <mx:HBox horizontalGap="10">
36       <mx:Button label="info"
37                  click="traceToFirebug(event);" id="infoButton" width="100" height="50"/>
38       <mx:Button label="error"
39                  click="traceToFirebug(event);" id="errorButton" width="100" height="50"/>
40       <mx:Button label="warn"
41                  click="traceToFirebug(event);" id="warnButton" width="100" height="50"/>
42       <mx:Button label="debug"
43                  click="traceToFirebug(event);" id="debugButton" width="100" height="50"/>
44  </mx:HBox>
45 </mx:Application>

Source

First of all: Feel free to check out the latest source via SVN ;-) .

  1 /**
  2 * Logging Flex and AS3 projects with Firebug
  3 *
  4 * @author   Jens Krause [www.websector.de]
  5 * @date  04/21/07
  6 * @see http://www.websector.de/blog/2007/04/21/logging-flex-2-and-as-3-apps-with-firebug-and-thunderbolt/
  7 * @source   http://flash-thunderbolt.googlecode.com/svn/trunk/as3/
  8 *
  9 */
 10 package org.osflash.thunderbolt
 11 {
 12     import flash.external.ExternalInterface;
 13     import flash.utils.describeType;
 14     import flash.utils.getQualifiedClassName;
 15     import flash.utils.getDefinitionByName;
 16     /**
 17    *
 18    */
 19     public class Logger
 20     {
 21         public static const LOG: String = "log";
 22         public static const INFO: String = "info";
 23         public static const WARN: String = "warn";
 24         public static const ERROR: String = "error";
 25         private static const MAX_DEPTH: int = 255;
 26         private static var depth: int;
 27         private static var logLevel: String;
 28         /**
 29         * Calls Firebugs command line API to write log information
 30         *
 31         * @param   msg   log Message
 32         * @param   obj   log object
 33         */
 34         public static function trace (msg: String = null, obj:Object = null): void
 35         {
 36             depth = 0;
 37             //
 38             // log description
 39             logLevel = (msg != null) ? Logger.getLogLevel(msg) : Logger.LOG;
 40             var txtMessage: String = (msg != null && msg.length>= 3) ? msg.slice(2) : "";
 41             var logMsg: String = logLevel.toUpperCase() + ": " + txtMessage;
 42             ExternalInterface.call("console." + logLevel, logMsg);
 43             //
 44             // log object
 45             if (obj) Logger.logProperties(obj);
 46         }
 47         /**
 48         * Logs nested instances and properties
 49         *
 50         * @param   logObj  log object
 51         * @param   id      short description of log object
 52         */
 53         private static function logProperties (logObj: *, id: String = null): void
 54         {
 55             ++ depth;
 56             var propID: String = id || "";
 57             if (depth <Logger.MAX_DEPTH)
 58             {
 59                 var description:XML = describeType(logObj);
 60                 var type: String = description.@name;
 61                 if (primitiveType(type))
 62                 {
 63                     var msg: String = (propID.length)   ?   "[" + type + "] " + propID + " = " + logObj
 64                                                         :   "[" + type + "] " + logObj;
 65                     ExternalInterface.call("console." + Logger.LOG, msg);
 66                 }
 67                 else if (type == "Object")
 68                 {
 69                     ExternalInterface.call("console.group", "[Object] " + propID);
 70                     for (var element: String in logObj)
 71                     {
 72                       logProperties(logObj[element], element);
 73                     }
 74                     ExternalInterface.call("console.groupEnd");
 75                 }
 76                 else if (type == "Array")
 77                 {
 78                     ExternalInterface.call("console.group", "[Array] " + propID);
 79                     for (var i: int = 0; i <logObj.length; i++)
 80                     {
 81                       logProperties(logObj[i]);
 82                     }
 83                     ExternalInterface.call("console.groupEnd");
 84                 }
 85                 else
 86                 {
 87                     var list: XMLList = description..variable;
 88                     if (list.length())
 89                     {
 90                         for each(var item: XML in list)
 91                         {
 92                             var propItem: String = item.@name;
 93                             var typeItem: String = item.@type;
 94                             // var ClassReference: Class = getDefinitionByName(typeItem) as Class;
 95                             var valueItem: * = logObj[propItem];
 96                             logProperties(valueItem, propItem);
 97                         }
 98                     }
 99                     else
100                     {
101                         logProperties(logObj, type);
102                     }
103                 }
104             }
105             else
106             {
107                 ExternalInterface.call("console." + Logger.WARN, "STOP LOGGING: More than " + depth + " nested objects or properties");
108             }
109         }
110         /**
111         * Checking for primitive types
112         *
113         * @param   type        type of object
114         * @return  isPrimitiveType  isPrimitiveType
115         *
116         */
117         private static function primitiveType (type: String): Boolean
118         {
119             var isPrimitiveType: Boolean;
120             switch (type)
121             {
122                 case "Boolean":
123                     isPrimitiveType = true;
124                 break;
125                 case "void":
126                     isPrimitiveType = true;
127                 break;
128                 case "int":
129                     isPrimitiveType = true;
130                 break;
131                 case "uint":
132                     isPrimitiveType = true;
133                 break;
134                 case "Number":
135                     isPrimitiveType = true;
136                 break;
137                 case "String":
138                     isPrimitiveType = true;
139                 break;
140                 case "undefined":
141                     isPrimitiveType = true;
142                 break;
143                 case "null":
144                     isPrimitiveType = true;
145                 break;
146                 default:
147                     isPrimitiveType = false;
148             }
149             return isPrimitiveType;
150         }
151         /**
152         * Translates log keys to Firebug log levels,
153         * which based on zeroi's key mapping
154         * @see  http://www.osflash.org/zeroi/
155         *
156         * @param   msg
157         * @return  level description
158         *
159         */
160         private static function getLogLevel (msg: String): String
161         {
162             var firstChar: String = (msg.charAt(1) == " ") ? msg.charAt(0).toLowerCase() : "d";
163             var level: String;
164             switch (firstChar)
165             {
166                 case "i":
167                     level = Logger.INFO;
168                 break;
169                 case "w":
170                     level = Logger.WARN;
171                 break;
172                 case "e":
173                     level = Logger.ERROR;
174                 break;
175                 case "d":
176                     level = Logger.LOG;
177                 break;
178                 default:
179                     level = Logger.LOG;
180             }
181             return level;
182         }
183     }
184 }

Feedback

Feedback and suggestions for improvement are welcome ;-) If you'd like to join the Flash-ThunderBolt project just drop me an email or feel free to post a comment.

Any feedback?

comments powered by Disqus