<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JonnyReeves.co.uk &#187; logging</title>
	<atom:link href="http://www.jonnyreeves.co.uk/tag/logging/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jonnyreeves.co.uk</link>
	<description>Actionscript, Flash, PHP and stuff</description>
	<lastBuildDate>Mon, 19 Jul 2010 15:36:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Logging in ActionScript 3</title>
		<link>http://www.jonnyreeves.co.uk/2010/02/logging-in-actionscript-3/</link>
		<comments>http://www.jonnyreeves.co.uk/2010/02/logging-in-actionscript-3/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 20:27:36 +0000</pubDate>
		<dc:creator>Jonny</dc:creator>
				<category><![CDATA[ActionScript 2]]></category>
		<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[logging]]></category>

		<guid isPermaLink="false">http://www.jonnyreeves.co.uk/?p=169</guid>
		<description><![CDATA[Logging is a fundamental part of any mid to large scale application, your application needs to be able to talk to other developers and Q&#038;A engineers to help diagnose problems and gain insight into what&#8217;s going on under the hood.  Jesse Warden recently wrote an excellent article on logging, however, my own implementation of [...]]]></description>
			<content:encoded><![CDATA[<p>Logging is a fundamental part of any mid to large scale application, your application needs to be able to talk to other developers and Q&#038;A engineers to help diagnose problems and gain insight into what&#8217;s going on under the hood.  Jesse Warden recently wrote <a href="http://jessewarden.com/2010/02/consulting-chronicles-3-preventing-fire-drills-crises-by-removing-land-mines-and-using-diagnostic-tools.html">an excellent article on logging</a>, however, my own implementation of logging AS3 apps differs so much that I thought it warranted a blog post.</p>
<h3>The Problems</h3>
<p>One of the most important things in OOP is to ensure that you avoid tight coupling; Jesse&#8217;s approach of using a static logger leaves your code scattered with a dependency on it.  </p>
<p>Another point that Jesse makes is how important it is to include the name of the enclosing class when writing a log message,</p>
<blockquote><p>&#8230; all log messages start with &#8220;ClassName::methodName&#8221; where ClassName is the name of the class you are in, and methodName is the current method the log message is in.  It seems a major pain at first, but I guarantee you when you start removing them 2 months later, you know EXACTLY where to find it vs. that one trace that stays there for weeks because no one found where the bastard is.
</p></blockquote>
<p>I couldn&#8217;t agree more with this, having come from working on a massive application with thousands of log messages, not knowing where a message was originating from would have been a nightmare.  However, Jesse&#8217;s approach is very manual and relies on your entire team being disciplined; not to mention the fact that as soon as you start refactoring that &#8220;ClassName::methodName&#8221; identifier is quickly going to get out of sync.</p>
<h3>A Commons Solution</h3>
<p>I feel that there is a simple solution to both the above problems in the form of the <a href="http://code.google.com/p/as3-commons/">AS3 Commons Logging Framework</a>.  The framework provides an abstraction of logging which means your code is not dependant on any one implementation, plus it has the added benefit of automatically adding the name of the Class when writing a log message; winner!</p>
<p>Usage is pretty straight forward, but requires a little more setup than Jesse&#8217;s static helper approach; first of all your request a static ILogger instance from the LoggerFactory at the top of your class and then you are free to use it throughout the Class to write log messages, for example:</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package uk.<span class="me1">co</span>.<span class="me1">jonnyreeves</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> MyClass<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Request an ILogger instance for this Class.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw3">static</span> const LOGGER : ILogger = LogFactory.<span class="me1">getClassLogger</span><span class="br0">&#40;</span>MyClass<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> MyClass<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Write a log message using the Logger instance.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LOGGER.<span class="me1">info</span><span class="br0">&#40;</span><span class="st0">&quot;Created instance of MyClass&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Using the TraceLogger implementation which the AS3 Commons Logger will default to, you would receive the following in your <a href="http://yourpalmark.com/2005/07/01/trace-from-the-browser-using-standard-trace/">Flash TraceLog</a>:</p>
<pre>
Sun Feb 21 10:33:29 GMT+0000 2010 [INFO]  uk.co.jonnyreeves.MyClass - Created instance of MyClass
</pre>
<p>The beauty of this approach is that the actual implementation of the ILogger interface is left to the LoggerFactory which means it can be switched at runtime.  Another neat benfit is that the name of the Logger is taken from the encolosing Class which created it (via <a href="http://code.google.com/p/as3-commons/source/browse/tags/as3-commons-logging/1.1/src/main/actionscript/org/as3commons/logging/LoggerFactory.as">LoggerFactory.getClassLogger()</a>).  This mean that is you rename the Class as part of a refactoring effort, all the log messages contained in said class will automatically update.</p>
<h3>Getting More Specific</h3>
<p>So I&#8217;ve mentioned that your can decide the ILogger implementation at runtime, let&#8217;s see an example of that in action.  My current Logging implementation of choice is the excellent DeMonsters Monster Debugger which reminds me a lot of the AS2 classic, LumnicBox in that it allows you to fully inspect the Object Graph at run time.</p>
<p>The first thing we need is to create an implementation of LogFactory which will return our ILogger instances upon request:</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package uk.<span class="me1">co</span>.<span class="me1">jonnyreeves</span>.<span class="me1">logging</span>.<span class="me1">util</span>.<span class="me1">monsterdebugger</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> nl.<span class="me1">demonsters</span>.<span class="me1">debugger</span>.<span class="me1">MonsterDebugger</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> org.<span class="me1">as3commons</span>.<span class="me1">logging</span>.<span class="me1">ILogger</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> org.<span class="me1">as3commons</span>.<span class="me1">logging</span>.<span class="me1">ILoggerFactory</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Provides a bridge between the AS3Commons Logging Framework and MonsterDebugger.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @author John Reeves<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> MonsterDebuggerLoggerFactory <span class="kw3">implements</span> ILoggerFactory <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Initialises MonsterDebugger<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @param target&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; The Base Object you wisht to start graphing from (usually you will supply the<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Display Root DisplayObject).<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @param clearConsole&nbsp; Clears MonsterDebugger&#8217;s Trace Console when the initial connection is made.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> MonsterDebuggerLoggerFactory<span class="br0">&#40;</span><span class="kw3">target</span> : <span class="kw3">Object</span>, clearConsole : <span class="kw3">Boolean</span> = <span class="kw2">true</span><span class="br0">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">new</span> MonsterDebugger<span class="br0">&#40;</span><span class="kw3">target</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>clearConsole<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MonsterDebugger.<span class="me1">clearTraces</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Factory Method, used to return an instance of ILogger to the AS3Commons Logging Framework.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> getLogger<span class="br0">&#40;</span><span class="kw3">name</span> : <span class="kw3">String</span><span class="br0">&#41;</span> : ILogger<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">new</span> MonsterDebuggerLogger<span class="br0">&#40;</span><span class="kw3">name</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Now all that&#8217;s left to do is to create the MonsterDebuggerLogger implementation of the ILogger interface; this will re-write all the LOGGER.info(), etc calls through to MonsterDebugger.</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package uk.co.jonnyreeves.logging.util.monsterdebugger <br />
{<br />
&nbsp; &nbsp; &nbsp; &nbsp; import org.as3commons.logging.util.MessageUtil;<br />
&nbsp; &nbsp; &nbsp; &nbsp; import nl.demonsters.debugger.MonsterDebugger;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; import org.as3commons.logging.LogLevel;<br />
&nbsp; &nbsp; &nbsp; &nbsp; import org.as3commons.logging.impl.AbstractLogger;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; /**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Provides a bridge between the AS3 Commons Logging implementation and Monster Debugger; it&#8217;s not perfect but it <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* works for the most part.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* The Target of the log message will always be the name of the logger.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* The Object of the log message will vary depending on the parameters passed. &nbsp;If the message string is empty<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* then the params Array will be logged. &nbsp;If the message string is not empty, the params Array will be used to<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* tokenise the message string.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Usage:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; LOGGER.debug(&quot;Hello World&quot;);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Outputs message: &quot;(String) Hello World&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; LOGGER.debug(&quot;Hello {0} {1}, &quot;Jonny&quot;, &quot;Reeves&quot;);&nbsp; &nbsp; &nbsp; &nbsp; // Outputs message: &quot;(String) Hello Jonny Reeves&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; LOGGER.debug(&quot;&quot;, [ 1, 2, 3 ]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Outputs message: &quot;(Array)&#8230;&quot; (which can then be inspected)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Incorrect usage:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; LOGGER.debug(&quot;Some Array&quot;, [1, 2, 3]);&nbsp; // Outputs message: &quot;(String) Some Array&quot; (which can&#8217;t be inspected)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @author John Reeves<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/<br />
&nbsp; &nbsp; &nbsp; &nbsp; public class MonsterDebuggerLogger extends AbstractLogger <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public var level : int = LogLevel.DEBUG;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public function MonsterDebuggerLogger(name : String) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super(name);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override protected function log(level : uint, message : String, params : Array) : void<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (level &gt;= this.level)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var target : Object = name;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var object : Object = getLogObject(message, params);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var colour : uint = getLogMessageColour(level);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MonsterDebugger.trace(target, object, colour);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private function getLogObject(message : String, params : Array) : Object <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (message == &quot;&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If the user only supplied a single param to log, we remove the params array which is enclosing it.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (params.length == 1) ? params.pop() : params;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return MessageUtil.toString(message, params);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private function getLogMessageColour(level : int) : uint <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var colour : int;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (level)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case LogLevel.FATAL:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case LogLevel.ERROR:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; colour = MonsterDebugger.COLOR_ERROR;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case LogLevel.WARN:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; colour = MonsterDebugger.COLOR_WARNING;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; colour = MonsterDebugger.COLOR_NORMAL;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return colour;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override public function get debugEnabled() : Boolean<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return LogLevel.DEBUG &gt;= level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override public function get errorEnabled() : Boolean<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return LogLevel.ERROR &gt;= level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override public function get infoEnabled() : Boolean<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return LogLevel.INFO &gt;= level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override public function get warnEnabled() : Boolean<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return LogLevel.WARN &gt;= level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; override public function get fatalEnabled() : Boolean<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return LogLevel.FATAL &gt;= level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
}<br />
&nbsp;</div>
<p>The code here is fairly self documenting with the protected log() method proxying all the logging requests through to MonsterDebugger.  Because the creators of the AS3Commons Logging Project specified the message param to have a datatype of String, we are forced to do a little bit of a workaround when we want to dump Objects out to the MonsterDebugger console.  There is an <a href="http://code.google.com/p/as3-commons/issues/detail?id=3">open ticket</a> on the AS3Commons project page should you wish to request a change.</p>
<p>The last piece of the puzzle is to swap the AS3Commons LoggingFactory implementation, this is very straight forward and requires a single line of code during your application&#8217;s startup routine (preferably before any logging takes place).</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package &nbsp;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> uk.<span class="me1">co</span>.<span class="me1">jonnyreeves</span>.<span class="me1">logging</span>.<span class="me1">util</span>.<span class="me1">MonsterDebuggerLoggerFactory</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">display</span>.<span class="me1">Sprite</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Application Entry Point.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @author John Reeves<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> MyApp <span class="kw3">extends</span> Sprite <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> MyApp<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LoggerFactory.<span class="me1">loggerFactory</span> = <span class="kw2">new</span> MonsterDebuggerLoggerFactory<span class="br0">&#40;</span><span class="kw3">this</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Once this is done you are free to start using the LoggingFactory as per the example further up the page.  Your log messages should now show up in the MonsterDebugger logging console.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonnyreeves.co.uk/2010/02/logging-in-actionscript-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The State of Logging in ActionScript 3</title>
		<link>http://www.jonnyreeves.co.uk/2008/10/the-state-of-logging-in-actionscript-3/</link>
		<comments>http://www.jonnyreeves.co.uk/2008/10/the-state-of-logging-in-actionscript-3/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 11:14:45 +0000</pubDate>
		<dc:creator>Jonny</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[utils]]></category>

		<guid isPermaLink="false">http://www.jonnyreeves.co.uk/?p=62</guid>
		<description><![CDATA[I&#8217;ve been looking at Logging Frameworks in ActionScript 3 over the past few days and I&#8217;m afraid that I&#8217;m slightly at a loss as for which approach is the best to take.  There are a few Logging Frameworks out there, but Adobe has kindly supplied an intrinic Logging Framework, however, it&#8217;s not without it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been looking at Logging Frameworks in ActionScript 3 over the past few days and I&#8217;m afraid that I&#8217;m slightly at a loss as for which approach is the best to take.  There are a few Logging Frameworks out there, but Adobe has kindly supplied an intrinic Logging Framework, however, it&#8217;s not without it&#8217;s shortcomings.</p>
<p>The biggest problem that I&#8217;ve come up against is that there is no easy way to set the Category for the Log.  The Flex Logging Framework allows you to set the category of the log when you retrieve the ILogger instance.  This can in turn be used by the Log Filtering system to specify which categories you would like to log.  Ideally you set the category String to be the name of the Class you are currently Logging, however, due to the rather shaky reflection tools available, there&#8217;s no easy way to automatically get the name of the current Class.  To compound the problem even further, getQualifiedClassName returns illegal characters (The semi-colon separating the Package and the Class Name) and Flex Logging Framework will throw and Illegal Arguments error if you try and use it as the category name.  So, in order to have automatic categories generated, we have to do a bit of a curly shuffle with a StackTrace and a Helper Method</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package uk.<span class="me1">co</span>.<span class="me1">jonnyreeves</span>.<span class="me1">logging</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> mx.<span class="me1">logging</span>.<span class="me1">ILogger</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> mx.<span class="me1">logging</span>.<span class="me1">ILoggingTarget</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> mx.<span class="me1">logging</span>.<span class="kw3">Log</span>;&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">import</span> flash.<span class="me1">utils</span>.<span class="me1">getQualifiedClassName</span>;&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Flex Logger Helper, automatically returns the Category Name when used inside<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* a Class.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @author jonny reeves<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> Logger <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Returns an instance of Flex Logger with the correct category name for the calling Class<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @return ILogger instance with the correct category set for the calling Class.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw3">static</span> <span class="kw2">function</span> getLogger<span class="br0">&#40;</span><span class="br0">&#41;</span> : ILogger<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> category : <span class="kw3">String</span> = <span class="st0">&quot;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; category = getCallerFromStackTrace<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">Log</span>.<span class="me1">getLogger</span><span class="br0">&#40;</span>category<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Triggers a StackTrace and extracts the calling method from it, neat.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw3">static</span> <span class="kw2">function</span> getCallerFromStackTrace<span class="br0">&#40;</span><span class="br0">&#41;</span> : <span class="kw3">String</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> callerMethod : <span class="kw3">String</span> = <span class="st0">&quot;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> nullArray : <span class="kw3">Array</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Pop a StackTrace by creating a RunTime error.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nullArray.<span class="kw3">push</span><span class="br0">&#40;</span><span class="st0">&quot;whoops&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">catch</span> <span class="br0">&#40;</span><span class="kw3">e</span> : <span class="kw3">Error</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> stackTrace : <span class="kw3">String</span> = <span class="kw2">new</span> <span class="kw3">Error</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getStackTrace</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Extract the ClassName from the StackTrack</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>stackTrace != <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> parts : <span class="kw3">Array</span> = <span class="kw2">new</span> <span class="kw3">Array</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stackTrace.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>.<span class="kw3">join</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parts = stackTrace.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;&nbsp; &nbsp; &nbsp; at &quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>parts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> != <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Handle Both Class Init and internal method cases</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>parts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span>.<span class="kw3">indexOf</span><span class="br0">&#40;</span><span class="st0">&quot;$cinit&quot;</span><span class="br0">&#41;</span> != <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callerMethod = parts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;$cinit&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callerMethod = parts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;/&quot;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> getCategoryNameFor<span class="br0">&#40;</span>callerMethod<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Helper method which takes an ActionScript 3 Formatted Class Name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* and replaces the semi-colons seperating the package and Class name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* with a Single Period for use as teh Flex Logging Category name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @param qualifiedClassName<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @return String Legal Flex Logging Category String<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw3">static</span> <span class="kw2">function</span> getCategoryNameFor<span class="br0">&#40;</span>qualifiedClassName : <span class="kw3">String</span><span class="br0">&#41;</span> : <span class="kw3">String</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> qualifiedClassName.<span class="kw3">indexOf</span><span class="br0">&#40;</span><span class="st0">&quot;::&quot;</span><span class="br0">&#41;</span> &gt; <span class="nu0">-1</span> ? qualifiedClassName.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;::&quot;</span><span class="br0">&#41;</span>.<span class="kw3">join</span><span class="br0">&#40;</span><span class="st0">&quot;.&quot;</span><span class="br0">&#41;</span> : qualifiedClassName;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This can now be used inside any Class you wish to Log by delcaring a private, static instance of ILogger, for example:</p>
<div class="dean_ch" style="white-space: nowrap; overflow: scroll;">
package uk.<span class="me1">co</span>.<span class="me1">jonnyreeves</span>.<span class="me1">logging</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">class</span> LoggingExample<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Instance of the Flex Logging Framework via the Logger Helper Class which will<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* automatically set the Category name to uk.co.jonnyreeves.logging.LoggingExample<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">private</span> <span class="kw3">static</span> <span class="kw2">var</span> Logger : ILogger = Logger.<span class="me1">getLogger</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/**<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* You can now log away, don&#8217;t forget to initialise your Flex Logger Instance (Log) first<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* by setting the Target Publisher (not shown).<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">public</span> <span class="kw2">function</span> LoggingExample<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Logger.<span class="me1">info</span><span class="br0">&#40;</span><span class="st0">&quot;Hello World!&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Although this is helpful it still does not address a couple of other fundamental issues:</p>
<ul>
<li>The output from the Flex Logging Framework does not include the enclosing method or line number from which the error was triggered (although this information can extracted from a StackTrace and automatically appended to the Logged Message by the Publisher).</li>
<li>The Flex Logging Framework does not intelligently handle datatypes &#8211; unfortunately we can only passing String&#8217;s to Flex Logger &#8211; however, we can get around this by making use of 3rd Party Consoles such as Thunderbolt (which also, helpfully includes a LoggingTarget).</li>
<li>Although the Flex Logging Framework allows you to supply a custom Filters Array (and this can even be updated at runtime), it does not appear to include a simple way to configure this via an external XML configuration file.  However, I&#8217;m fairly confident that I can roll my own (just a shame that I have to!)</li>
</ul>
<p>I&#8217;m going to be working on the three points above over the next few days and see if I can come up with a solution which stays as faithful to the intrinsic Logging framework as possible but allows the flexibility of some of the other Loggers out there (Luminic Box, XRay, etc).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonnyreeves.co.uk/2008/10/the-state-of-logging-in-actionscript-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
