fa!5 49:19:375 [Image/load():38] this is a trace point fa!5 49:19:375 [Image/load():43] how did this get called? fa!5 +--[Image():28] fa!5 +--[HomePageImage():23] fa!5 +--[HomeDefault():67] fa!5 21:59:750 [FileInfo():39] this is my obj (print_r) com.flickaway::FileInfo => fa!5 [fver]:int => 0 fa!5 [caption]:String => "" fa!5 [fidp]:String => "0/0/7/a1_373lrkz9z"
/** * This provides full, quick and no tracing capabilities (as much as ActionScript allows) via the exception * mechanism, which I imagine could impede performance. It provides caller information. * * Use: set_trace_type with TYPE_NONE, TYPE_QUICK and TYPE_FULL + TYPE_REMOTE (new - to test with non-debug flash player) * * @author Glen * @copyright 2006 flickaway.com * @version $Id: Trace.as 1710 2008-08-21 16:51:03Z glen $ */ package com.flickaway { import flash.events.StatusEvent; import flash.net.LocalConnection; import flash.utils.describeType; public class Trace { static public const TYPE_NONE :uint = 0; // To turn off tracing (for production) and save cycles static public const TYPE_QUICK :uint = 1; // To avoid generating and parsing stacktrace + using trace() for output static public const TYPE_FULL :uint = 2; // The norm - Full tracing + using trace() for output static public const TYPE_REMOTE :uint = 3; // Full tracing, but sending it to another swf via LocalConnection static private var my_type:uint = TYPE_FULL; // defaults to FULL static private var conn:LocalConnection; static private var lc_name:String = '_flickaway_trace'; // Local connection name static private var lc_func:String = 'log'; // Local connection function static public function set_trace_type(type:uint):void { Trace.my_type = type; if (type == Trace.TYPE_REMOTE) { Trace.conn = new LocalConnection(); Trace.conn.addEventListener(StatusEvent.STATUS, Trace.on_status_handler); } } static public function on_status_handler(event:StatusEvent):void { switch (event.level) { case "status" : break; // succeeded case "error" : trace("FA Trace: LocalConnection to " + Trace.lc_name + ":" + Trace.lc_func + " failed."); break; } } static public function log(level:uint, msg:String):void { switch (Trace.my_type) { case TYPE_NONE: return; case TYPE_FULL: // conditional logic inside case TYPE_REMOTE: Trace.log_full(level, msg); break; // dito case TYPE_QUICK: Trace.log_quick(level, msg); break; default: throw new Error("Cannot handle trace type of " + Trace.my_type); } } static public function error(level:uint, msg:String):void { switch (Trace.my_type) { case TYPE_NONE: Trace.log_full(level, msg); break; // on production systems, we want to see these still case TYPE_FULL: // conditional logic inside case TYPE_REMOTE: Trace.log_full(level, msg); throw new Error(msg); break; // Log AND throw an exception case TYPE_QUICK: Trace.log_full(level, msg); throw new Error(msg); break; // Log AND throw an exception default: throw new Error("Cannot handle trace type of " + Trace.my_type); } } static public function codetrace(level:uint, msg:String):void { switch (Trace.my_type) { case TYPE_NONE: return; case TYPE_FULL: // conditional logic inside case TYPE_REMOTE: Trace.codetrace_full(level, msg); break; // dito case TYPE_QUICK: Trace.log_quick(level, msg); break; // in quick mode - we cannot do the codetrace default: throw new Error("Cannot handle trace type of " + Trace.my_type); } } static public function print_r(level:uint, msg:String, obj:*):void { switch (Trace.my_type) { case TYPE_NONE: return; case TYPE_FULL: // conditional logic inside case TYPE_REMOTE: Trace.print_r_full(level, msg, obj); break; // dito case TYPE_QUICK: Trace.print_r_quick(level, msg, obj); break; default: throw new Error("Cannot handle trace type of " + Trace.my_type); } } //================================================================================================================================== // // QUICK TRACE // //================================================================================================================================== static private function log_quick(level:uint, line:String):void { var d:Date = new Date(); var m = d.getMinutes(); var s = d.getSeconds(); var ms = d.getMilliseconds(); Trace.write("fa!" + level + "-" + (m>=10?m:'0'+m) + ":" + (s>=10?s:'0'+s) + ":" + (ms>=100?ms:(ms>=10?'0'+ms:'00'+ms)) + " " + line); } static private function print_r_quick(level:uint, msg:String, obj:*):void { Trace.log(level, msg + " (print_r of <?something?>)"); } //================================================================================================================================== // // FULL TRACE // //================================================================================================================================== static private function log_full(level:uint, msg:String, snum:uint=3):void { // FROM: // http://snippets.dzone.com/posts/show/3703 //---------------------------------------------------------------------------------------------------------------- // With debugging turned on, this is what we get: // // Error // <tab>at com.flickaway::Trace$/log_full()[D:\web\flickaway_branch\flash\lib\com\flickaway\Trace.as:83] // <tab>at com.flickaway::Trace$/print_r_full()[D:\web\flickaway_branch\flash\lib\com\flickaway\Trace.as:114] // <tab>at com.flickaway::Trace$/print_r()[D:\web\flickaway_branch\flash\lib\com\flickaway\Trace.as:46] // <tab>at com.flickaway::Params()[D:\web\flickaway_branch\flash\lib\com\flickaway\Params.as:36] <==== this line we want // <tab>at com.flickaway::Params$/get_instance()[D:\web\flickaway_branch\flash\lib\com\flickaway\Params.as:27] // <tab>at HomeDefault()[D:\web\flickaway_branch\flash\homepage\HomeDefault.as:57] // <tab>at com.flickaway::Params()[D:\web\flickaway_branch\flash\lib\com\flickaway\Params.as:36]) // // with debugging turned off: // // Error // <tab>at com.flickaway::Trace$/log_full() // <tab>at com.flickaway::Trace$/print_r_full() // <tab>at com.flickaway::Trace$/print_r() // <tab>at com.flickaway::Params() // <tab>at com.flickaway::Params$/get_instance() // <tab>at HomeDefault() //---------------------------------------------------------------------------------------------------------------- var e = new Error(); var str:String = e.getStackTrace(); // get the full text str //Trace.write("str.length=" + str); if (str == null) // means we aren't on the Debug player { Trace.log_it(level, "(!debug) " + msg); } else { var stacks:Array = str.split("\n"); // split into each line var caller:String = Trace.gimme_caller(stacks[snum]); // get the caller for just one specific line in the stack trace Trace.log_it(level, caller + " " + msg); } } static private function codetrace_full(level:uint, msg:String, snum:uint=3):void { var e:Error = new Error(); //---------------------------------------------------------------------------------------------------------------- // This is just like log_full() - except we print out all lines in the stack, starting at snum //---------------------------------------------------------------------------------------------------------------- var str:String = e.getStackTrace(); // get the full text str if (str == null) // means we aren't on the Debug player { Trace.log_it(level, "no_debug " + msg); } else { var stacks:Array = str.split("\n"); // split into each line var caller:String = Trace.gimme_caller(stacks[snum]); // get the caller info for just one specific line in the stack trace Trace.log_it(level, caller + " " + msg); if (snum < stacks.length) // this means there's more in the stack to print out { for (var i = snum+1; i < stacks.length; i++) { caller = Trace.gimme_caller(stacks[i]); Trace.write("fa!" + level + " +--" + caller); } } } } /** * Returns a string like "[HomeDefault():51]" - line number present only if "permit debugging" is turned on. */ static private function gimme_caller(line:String):String { //------------------------------------------------------------------------------------------------- // the line can look like any of these (so we must be able to clean up all of them): // // <tab>at com.flickaway::Params() // <tab>at com.flickaway::Params()[D:\web\flickaway_branch\flash\lib\com\flickaway\Params.as:36] // <tab>at HomeDefault() // <tab>at HomeDefault()[D:\web\flickaway_branch\flash\homepage\HomeDefault.as:57] //------------------------------------------------------------------------------------------------- var dom_pos:int = line.indexOf("::"); // find the '::' part var caller:String; if (dom_pos == -1) { caller = line.substr(4); // just remove '<tab>at ' beginning part (4 characters) } else { caller = line.substr(dom_pos+2); // remove '<tab>at com.flickaway::' beginning part } var lb_pos:int = caller.indexOf("["); // get position of the left bracket (lb) if (lb_pos == -1) // if the lb doesn't exist (then we don't have "permit debugging" turned on) { return "[" + caller + "]"; } else { var line_num:String = caller.substr(caller.lastIndexOf(":")); // find the line number caller = caller.substr(0, lb_pos); // cut it out - it'll look like ":51]" return "[" + caller + line_num; // line_num already has the trailing right bracket } } static private function print_r_full(level:uint, msg:String, obj:*):void { Trace.log_full(level, msg + " (print_r) " + Trace.pr(level, obj), 4); } // FROM: // http://blogs.grf-design.com/archives/2007/07/actionscript_3.html static private function pr(level:uint, o:*, name:String = "", recur:int = 0):String { var result:String = ""; var type:String = typeof(o); var desc:XML = describeType(o); if (type == "function") { return result; } // meta data of object if (recur != 0) { result += "\nfa!" + level + " "; for (var i:int = 0; i < recur; ++i) { result += " "; } } if (name) { result += '[' + name + ']:'; } result += desc.@name + ' => '; // content of object switch (type) { case "boolean": case "number": result += String(o); break; case "string": result += '"' + String(o) + '"'; break; case "xml": result += o.toXMLString(); break; 0 case "object": if (desc.@name == "Object" || desc.@name == "Array") { for (var key:String in o) { //result += "\n"; result += pr(level, o[key], key, (recur + 1)); } } else { var prop:XML; // -- properties for each (prop in desc.variable) { result += pr(level, o[prop.@name], prop.@name, (recur + 1)); } // -- methods for each (prop in desc.method) { result += pr(level, o[prop.@name], prop.@name, (recur + 1)); } } break; case "function": // I dont want to print out functions result += String(o); break; default: Trace.write("ERROR: not handling type: " + type); } return result; } static private function log_it(level:uint, line:String):void { var d:Date = new Date(); var m = d.getMinutes(); var s = d.getSeconds(); var ms = d.getMilliseconds(); Trace.write("fa!" + level + " " + (m>=10?m:'0' + m) + ":" + (s>=10?s:'0' + s) + ":" + (ms>=100?ms:(ms>=10?'0' + ms:'00' + ms)) + " " + line); } static private function write(str:String):void { if (Trace.my_type == Trace.TYPE_REMOTE) { Trace.conn.send(Trace.lc_name, Trace.lc_func, str); } else { trace(str); } } } }