Ultrashock Forums > Flash > ActionScript
AS3 - Can you. trace a line #

You are currently viewing our website as a guest which gives you limited access to forums, files and other resources.

Click here to join now for free, and start interacting with our members, download files and much more!

Click here if you are looking for our Flash files and other professional assets.
 
Post Reply | View first unread | Rate Thread Search this Thread | Thread Tools | Display Modes

#1
Bookmark and Share!
AS3 - Can you. trace a line #
Old 2008-03-12

Just wondering if u can trace a line # in ActionScript 3, similiar to other languages _line_
http://www.CreativeScientist.com
postbit arrow 4 comments | 1507 views postbit arrow Reply: with Quote   
Registered User
Artofacks1 is offline
seperator
Posts: 2,537
2002-04-18
Artofacks1 lives in United States
seperator

Ultrashock Member Comments:
Artofacks1 Artofacks1 is offline Artofacks1 lives in United States 2008-03-13 #2 Old  
Anyone know?
Reply With Quote  
Nutrox's Avatar Nutrox Nutrox is offline Nutrox lives in United Kingdom 13 Creative Assets 2008-03-13 #3 Old  
That isn't possible in AS3 as far as I know. You shouldn't need that though if you use the debugger in Flash or Flex, both of those should show you any code that throws runtime errors.
Reply With Quote  
Artofacks1 Artofacks1 is offline Artofacks1 lives in United States 2008-03-13 #4 Old  
Reason I ask, is because when I am writing m code and I get nto race conditions I like to make traces something like this.

trace("line 136 " + variableName);

than some where else would trace line 146 or whatever, just t make sure that my code s running in he order want t to run. I know php _line_ has helped me a lot. even tough it undercounts he lines by one. But thanks for your reply.
Reply With Quote  
suki_babee suki_babee is offline 2008-08-06 #5 Old  
Yes you can..
Last edited by suki_babee : 2008-08-21 at 09:21.
UPDATED: all you need to do is:

var e:Error = new Error();
var s:String = e.getStackTrace();
trace(s);

this only works with the debug flash player (s=null otherwise). It gives you a stack trace with line numbers (line numbers only if you have "Permit Debugging" enabled when your SWF is published). I wrote a class to do this elegantly and I added a bunch more features. 3 ways to use it:

Trace.log(5, "this is a trace point"); // basic trace point
Trace.codetrace(5, "how did this get called"); // more interesting called within a stack
Trace.print_r(5, "this is my obj", obj); // traces out contents of obj or array (only public elements if instance)

And you can turn the trace off when you want better performance for a published swf:

Trace.set_trace_type(Trace.TYPE_NONE);


Sample output. I prefix with "fa!" ('fa' for FlickAway.com - but you can change that) followed by level (1 char), followed by timestamp (min:sec:milli) [caller] <msg>. The prefix is so I can filter out other swf tracing from mine when testing in Firefox + FlashTrace:
Code:
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"

com/flickaway/Trace.as:
Code:
/**
* 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);
      }
    }

  }
}
Reply With Quote  
Thread Tools
Display Modes Rate This Thread
Rate This Thread: