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.