The Logging API contained withing the Flex Framework allows you to control the messages logged in an application. By controlling, I mean filtering log messages by the package or class name they were logged from, and by their level (ALL, DEBUG, INFO, WARN, ERROR, FATAL).
Logging messages is done by calling one of the log methods on an ILogger instance, e.g. logger.debug("I'm a log message"), and replaces the need to call trace(). The Logging API offers standard support for logging to the console using the TraceTarget and you can also create your own log targets by implementing the ILoggingTarget interface.
An Example
Here is an example showing how to configure a trace target and add it to the Log manager class. (Example taken from the Log documentation in the Flex 2 livedocs).
-
// Create a target.
-
var logTarget:TraceTarget = new TraceTarget();
-
-
// Log only messages for the classes in the mx.rpc.* and
-
// mx.messaging packages.
-
logTarget.filters=["mx.rpc.*","mx.messaging.*"];
-
-
// Log all log levels.
-
logTarget.level = LogEventLevel.ALL;
-
-
// Add date, time, category, and log level to the output.
-
logTarget.includeDate = true;
-
logTarget.includeTime = true;
-
logTarget.includeCategory = true;
-
logTarget.includeLevel = true;
-
-
// Add the target to the Log
-
Log.addTarget(logTarget);
Once the Log is configured with a target, we can request a logger from the Log manager class and write a message with it.
-
// Get a logger from the Log manager
-
var logger:ILogger = Log.getLogger("com.domain.MyClass");
-
-
// Write a log message
-
logger.debug("debug message");
-
logger.error("error message");
When requesting a logger from the Log manager, we pass in the name of the class we will be logging from. This will allow us to filter the messages by specifying of which classes we want to see the logs.
One of the things you will typically want to do is change the configuration of the logger based on the environment the application is running on. For instance, you might want to use the TraceTarget and a debug level of ALL when doing local builds on your development machine and change this to a socket target and a level of WARN or ERROR when deploying to a test server.
However, changing these settings demands a recompile of the entire application. To avoid this we can leverage the power of Prana and configure the logger in the application context. Let's begin by configuring a trace target.
-
<object id="traceTarget" class="mx.logging.targets.TraceTarget">
-
<property name="includeCategory" value="true"/>
-
<property name="includeDate" value="true"/>
-
<property name="includeLevel" value="true"/>
-
<property name="includeTime" value="true"/>
-
<property name="level" value="0"/><!-- Log Levels: 0, 2, 4, 6, 8, 1000 -->
-
<property name="filters">
-
<array>
-
<value>mx.rpc..*</value>
-
<value>mx.messaging.*</value>
-
</array>
-
</property>
-
</object>
This will result in a trace target similar to the one we configured earlier in code. Notice that the level is an int because we can't use the constants of the LogEventLevel class inside the application context.
The only thing that is left to configure the Log manager is to add the trace target to it. Since this happens through a static method call (Log.addTarget()) on the Log class, we need to use a MethodInvokingObject in our application context. This allows us to call a method on an object or a class and pass in arguments by means of object initialization. The method defined in the MethodInvokingObject will automatically be invoked after all its properties have been set.
-
<object id="log" class="org.pranaframework.ioc.factory.MethodInvokingObject">
-
<property name="target" value="mx.logging.Log" type="Class"/>
-
<property name="method" value="addTarget"/>
-
<property name="arguments">
-
<array>
-
<ref>traceTarget</ref>
-
</array>
-
</property>
-
</object>
And that's a wrap. Notice that the addLogger() method is static, but you don't need to instruct the application context about it. The 'target' property takes an object or a class. The 'method' property takes the name of a (static) method. The arguments are passed in as an array.
You can get the code from the SVN repository which can be found on the Prana project page. As usual, any feedback is greatly appreciated. Enjoy Prana!
Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
Christophe Herreman is a software developer living in Belgium. He's working on high-end Flex and AIR solutions at 
November 19th, 2007 at 5:38 am
Hey, nice writeup. I’m very interested in Prana, and this article combined with the one someone else wrote about swapping out the service layer at runtime (I don’t have the link on me right now) are really good knowledge to have.
April 10th, 2008 at 4:39 pm
Hmm, get IoC working generally with prana, but this seems to throw its toys out of the pram
)
Error: A class with the name ‘mx.logging.targets.TraceTarget’ could not be found.
at org.pranaframework.utils::ClassUtils$/forName()[C:\Users\herremanc\workspace\prana\main\src\org\pranaframework\utils\ClassUtils.as:78]
at org.pranaframework.ioc::ObjectContainer/getObject()[C:\Users\herremanc\workspace\prana\main\src\org\pranaframework\ioc\ObjectContainer.as:121]
at org.pranaframework.ioc.parser::XmlObjectDefinitionsParser/parseObjectNode()[C:\Users\herremanc\workspace\prana\main\src\org\pranaframework\ioc\parser\XmlObjectDefinitionsParser.as:150]
at org.pranaframework.ioc.parser::XmlObjectDefinitionsParser/parse()[C:\Users\herremanc\workspace\prana\main\src\org\pranaframework\ioc\parser\XmlObjectDefinitionsParser.as:125]
at org.pranaframework.ioc.loader::XmlObjectDefinitionsLoader/onLoaderComplete()[C:\Users\herremanc\workspace\prana\main\src\org\pranaframework\ioc\loader\XmlObjectDefinitionsLoader.as:84]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
Tried “import mx.logging.targets.TraceTarget;” in the Application but no dice. Any ideas?
April 10th, 2008 at 8:22 pm
Hi Matt,
did you also reference the TraceTarget class somewhere in your code? Importing is not enough. You really need to refer to it via a variable or a static code block.
private static var includedClasses:Array = [TraceTarget];
or with a static code block
{
TraceTarget
}
April 11th, 2008 at 10:14 am
Awesome! Thanks so much for the feedback
)
October 6th, 2008 at 2:44 pm
Hello Christophe.
Is it possible to create a template for “MethodInvokingObject” to invoke “addTarget” method several times on? I have multiple log targets so I’m wondering if there is shorter notation to add my targets to the Log object.
October 6th, 2008 at 3:25 pm
Hi Igor,
That is unfortunately not possible since templates only replace string at this moment. We could (should) introduce the “parent” attribute on a bean so you’d have to type less. Or we could also have a post processor that adds all ILoggingTarget implementations to the Log it finds in the application context.
Both ideas seem interesting to me and the latter might be particularly interesting for FlexXMLApplicationContext.
Thoughts?
October 6th, 2008 at 3:45 pm
Hey Igor,
I just added org.pranaframework.ioc.factory.config.LoggingTargetObjectPostProcessor to the svn. This is an object post processor that will auto-register all ILoggingTarget implementations in the application context to the Log.
If you want to use it now, just add this line in the constructor of FlexXMLApplicationContext:
addObjectPostProcessor(new LoggingTargetObjectPostProcessor());
You can then just define logging targets in your context without the need to add them manually via a MethodInvokingObject.
I can’t commit FlexXMLApplicationContext now since I have some more pending changes, but it will be commited in the coming days.
October 6th, 2008 at 4:22 pm
Thank you very much for the quick response, Christophe! I will try your suggestion.
Another question: could I use the result returned by “MethodInvokingObject” (or some another entity) to initialize some property? Or it’s not possible?
October 6th, 2008 at 5:00 pm
Hi Igor, do you mean referencing another object defined in the application context? If so, you can do this with the ref attribute and element.
October 6th, 2008 at 5:11 pm
No, I mean something like:
{object class=”vegas.logging.targets.XPanelTarget”}
{property name=”includeCategory” value=”true” /}
{property name=”includeDate” value=”false” /}
{property name=”includeLevel” value=”true” /}
{property name=”includeTime” value=”false” /}
{property name=”level”}
{object class=”org.pranaframework.ioc.factory.MethodInvokingObject”}
{property name=”target” value=”VegasLoggerHelper” type=”Class” /}
{property name=”method” value=”toVegasLogEventLevel” /}
{property name=”arguments”}
{array}
{value}4{/value}
{/array}
{/property}
{/object}
{/property}
{/object}