Flex Logging Framework

So I’ve recent;y been tasked with building up an interface for the Flex logging framework… Which surprisingly wasn’t that hard. I learn by example, so the Flex language reference was completely useless. The provided example is completely whack IMO. extending a button to log? yeah that’s helpful in real world needs.

I’ve been working on refining it with the Esria chaps, but thought I’d share my simple little example.

So Flex has a whole logging framework inside it, which is great, and pretty darn easy to implement. I wrote this little example to help me test my understanding of it, as well as test different approaches. You can view the output, here. Not very flashy I know, but…

I created my own webservice debug target by extending the lineformatted target.

Let’s see the code.

This is my simple little MXML witha  button on it.

<mx:Script>
    <![CDATA[
        import mx.logging.LogEvent;
        import mx.logging.LogEventLevel;
        import as_files.logManager;
       
        public function logTester():void
        {
            var testTarget:String = "WebService";
            var testCategory:String = "John";
            var testEvent:LogEvent = new LogEvent();
             //We create a log event to hold our level and message.
            testEvent.level = LogEventLevel.INFO;
            testEvent.message = "ACK";
           
             //create an instance of my log manager (see code below) and call it’s logger function
            var writeLog:logManager = new logManager();
            writeLog.Logger(testEvent, testCategory, testTarget);
           
        }
       
    ]]>
</mx:Script>

<mx:Panel label="test">
    <mx:Button label="click me" click="logTester()"/>
</mx:Panel>   

This is the logmanager class.

package as_files
{
    import flash.events.Event;
    import mx.logging.Log;
    import mx.logging.LogEvent;   
    import mx.logging.ILogger;
    import mx.logging.targets.TraceTarget;
    import mx.logging.targets.MiniDebugTarget;
    import mx.logging.targets.LineFormattedTarget;
    import mx.logging.ILoggingTarget;
    import as_files.WebServiceTarget;
   
    public class logManager
    {
        //Use this as a model for my functionality.
       
       
        //Handle categories

        public function Logger(L:LogEvent, category:String, target:String):void
        {
            var myTarget:ILoggingTarget;
            //I made a switch so that I could select the target myself based on my need. One line of code could write to a webservice, another might just write to trace.
            switch(target)
                {
                     case ‘Line’:
                        myTarget = new LineFormattedTarget();
                        break;
                     case ‘MiniDebug’:
                         myTarget = new MiniDebugTarget();
                        break;
                     case ‘WebService’:
                         myTarget = new WebServiceTarget(‘http://www.red-omega.com/DummyLoggingWS/webservice.cfc?wsdl’, ‘Listener’);
                        break;
                     //Trace will be default
                     case ‘Trace’:
                         myTarget = new TraceTarget();                        
                        break;
                     default:
                         myTarget = new TraceTarget();
                        break;
                }
               
            var myLogger:ILogger = Log.getLogger(category);           
           
            //You can filter your target on specific categories.
            myTarget.filters = [category];
            myTarget.level = L.level;
            //myTarget.addLogger(myLogger);
           
            //Add my target to teh logging system so when logs like what I am looking for arrive they are directed to the right place.
            Log.addTarget(myTarget);
       
            //handle the log level
            //It seems that the default behaviour is to log the selected level and those below. For my test I didn’t want that so I simply limited it.
            switch(L.level)
            {
                case 0:
                    myLogger.log(L.level, " GENERAL:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    break;
                case 2:
                    if (Log.isDebug()) {
                        myLogger.debug(" EVENT:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    }
                    break;
                case 4:
                    if (Log.isInfo()) {
                        myLogger.info(" INFO:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    }
                    break;
                case 6:
                    if (Log.isWarn()) {
                        myLogger.warn(" WARN:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    }
                    break;
                case 8:
                    if (Log.isError()) {
                        myLogger.error(" ERROR:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    }
                    break;
                case 1000:
                    if (Log.isFatal()) {
                        myLogger.fatal(" FATAL:   " + L.target + ":" + L.type + ". Message is: ‘{0}’", L.message);
                    }
                    break;
            }           
        }
       
        //Handle targets.
       
    }
}

The last little bit of code is my WebServiceTarget. All it does, you’ll see at the bottom is extend the lineformattedTarget and call a webservice with a block of text to be written. Presumably to a log file on a remote sever in siberia.

package as_files
{

import mx.rpc.soap.mxml.WebService;
import mx.core.mx_internal;
import mx.logging.targets.LineFormattedTarget;
import mx.rpc.AbstractOperation;

use namespace mx_internal;

/**
 *  Provides a logger target that outputs to a <code>LocalConnection</code>,
 *  connected to the MiniDebug application.
 */
public class WebServiceTarget extends mx.logging.targets.LineFormattedTarget
{

    //————————————————————————–
    //
    //  Constructor
    //
    //————————————————————————–

    /**
     *  Constructor.
     *
     *  <p>Constructs an instance of a logger target that will send
     *  the log data to the MiniDebug application.</p>
     *
     *  @param connection Specifies where to send the logging information.
     *  This value is the name of the connection specified in the
     *  <code>LocalConnection.connect()</code> method call in the remote SWF,
     *  that can receive calls to a <code>log()</code> method with the
     *  following signature:
     *  <pre>
     *    log(… args:Array)
     *  </pre>
     *  Each value specified in the <code>args</code> Array is a String.
     *
     *  @param method Specifies what method to call on the remote connection.
     */
    public function WebServiceTarget(service:String, method:String)
    {
        super();
        _ws = new WebService();
        _service = service;
        _method = method;
    }

    //————————————————————————–
    //
    //  Variables
    //
    //————————————————————————–

    /**
     *  @private
     */
    private var _ws:WebService;
   
    /**
     *  @private
     *  The name of the method that we should call on the remote connection.
     */
    private var _method:String;

    /**
     *  @private
     *  The name of the connection that we should send to.
     */
    private var _service:String;

    //————————————————————————–
    //
    //  Overridden methods
    //
    //————————————————————————–

    /**
     *  @private
     *  This method outputs the specified message directly to the method
     *  specified (passed to the constructor) for the local connection.
     *
     *  @param message String containing preprocessed log message which may
     *  include time, date, category, etc. based on property settings,
     *  such as <code>includeDate</code>, <code>includeCategory</code>, etc.
     */
    override mx_internal function internalLog(message:String):void
    {
       
        _ws.loadWSDL(_service);
        _ws.useProxy = false;
       
        //_ws.addEventListener("result", wsLoginResult);
        //_ws.addEventListener("fault", wsLoginFault);
              
        var op:AbstractOperation;
        op = _ws[_method];
              
        var args:Object = new Object();
          
        args.LogData = message;
       
              
        op.arguments = args;
        op.send();
        //_lc.send(_connection, _method, message);
    }
}

}

I don’t for a second think that there aren’t better approaches, this is beta .01 of my logging attempts. It works and it shows how the built in logging functionality does what it does.

7 thoughts on “Flex Logging Framework

  1. jwilker Post author

    @lalit, I'm not sure what you mean by log the log messages. If they're writing to a text file, you could use that. Or do you mean write into the Fash log file?

  2. Lalit

    Hi,
    You showed the log messages in output.txt but u din't explain about how to configure such text files in flex project so that we
    can log the log messages in to it .If u can specify that method then ur blog will be more useful to the beginners like me.

  3. jwilker Post author

    @Nedu

    I believe I remember reading that you could store the log data in a Shared Object. I'm not sure Flash player has permission to create txt files on the host computer, I think it's only Shared Objects. Wouldn't you want your log on the server though? Vs the client's computer, where you have no access to it?

  4. Nedu

    Hi jwilker,
    I too have a problem in logging message to a .txt file.In the above example u have called webservice as a target. But I need to log messages at client side.( since,I'l be using different types of servers to host my app).Is there a feature in logging framework of flex that i can create a log file in my project itself(locally like log4j in java where u'l be giving the path of the file to create).

    ).

  5. Log w/ SharedObject

    […] Having your app keep a detailed log can be indispensable for figuring out tricky user-reported bugs. This is easy on the server-side, where you can use any logging framework or just write to a file. Flash includes the trace function, which is useful while developing, but nearly impossible to get from an end-user. Flex, however, has a good logging api that lets you put log statements anywhere you want. I’ve always wanted the interface to be as easy as trace, so I write a couple of scripts to make it easier. […]

  6. Shweta

    Hey,
    I am wondering if there is some sort of logging mechanism that I could use to log messages/errors from a Flex application. I would like the log to be created on the server.

    It would be great if there is something like Log4J in Flex.

    Thanks,
    Shweta

Comments are closed.