longsleep / as3-commons

Automatically exported from code.google.com/p/as3-commons
1 stars 1 forks source link

as3Commons-logging: addTargetRule not working with multiple targets #74

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

        import nl.qiy.engine.application.util.logging.StringBufferTarget; // implements ILoggingTarget
    import org.as3commons.logging.api.ILogger;
    import org.as3commons.logging.api.LOGGER_FACTORY;
    import org.as3commons.logging.api.getLogger;
    import org.as3commons.logging.setup.RegExpSetup;
    import org.as3commons.logging.setup.target.TraceTarget;

    var traceTarget:TraceTarget = new TraceTarget();
    var stringBufferTarget:StringBufferTarget = new StringBufferTarget();
    var regExSetup:RegExpSetup = new RegExpSetup()
        .addTargetRule(/^nl\.qiy\./, traceTarget)
        .addTargetRule(/^nl\.qiy\./, stringBufferTarget)
        .addTargetRule(/^Engine/, traceTarget)
        .addTargetRule(/^Engine/, stringBufferTarget)
        .addTargetRule(/^com\.asfusion\.mate/, traceTarget)
        .addTargetRule(/^com\.asfusion\.mate/, stringBufferTarget);
    LOGGER_FACTORY.setup = regExSetup;

What is the expected output? What do you see instead?

i expect both logging to my custom logger and to the flash builder console. But 
i only see logging to 
my custom stringBufferTarget. It looks like if the regex filter is the same you 
cannot log the same to multiple targets. I.e. that the stringbuffer target 
overwrites the rule for the tracetarget.

What version of the product are you using? On what operating system?
2.5.2 osx 10.6.7

Please provide any additional information below.

Original issue reported on code.google.com by arno...@gmail.com on 24 Aug 2011 at 10:33

GoogleCodeExporter commented 9 years ago
Indeed it works like that.

If you want two or more targets to be used with RegExpSetup just use 
mergeTargets: Here is a example for your code:

    var myTargets: MergedTargets = mergeTargets( new StringBufferTarget, new TraceTarget );
    LOGGER_FACTORY.setup = new RegExpSetup()
        .addTargetRule(/^nl\.qiy\./, myTargets)
        .addTargetRule(/^Engine/, myTargets)
        .addTargetRule(/^com\.asfusion\.mate/, myTargets);

Is that sufficient?

Original comment by mastakan...@gmail.com on 24 Aug 2011 at 11:43

GoogleCodeExporter commented 9 years ago
Ah ok, thanx for the quick answer. The reason i want to execute code like i 
pasted is that I build  a factory for spring actionscript so you can configure 
logging and multiple targets from outside. Usage looks like this:

    <object id="stringBufferTarget"
        class="nl.qiy.engine.application.util.logging.LoggingTargetFactory">
        <property value="nl.qiy.engine.application.util.logging.StringBufferTarget" name="loggingTargetClass" />
        <property value="${logging.format}" name="format" />
        <property value="${logging.level}" name="level" />
        <property name="filters">
            <array>
                <value>nl.qiy</value>
                <value>Engine</value>
            </array>
        </property>
    </object>

    <object id="traceTarget"
        class="nl.qiy.engine.application.util.logging.LoggingTargetFactory">
        <property value="org.as3commons.logging.setup.target.TraceTarget" name="loggingTargetClass" />
        <property value="${logging.format}" name="format" />
        <property value="${logging.level}" name="level" />
        <property name="filters">
            <array>
                <value>nl.qiy</value>
                <value>Engine</value>
            </array>
        </property>
    </object>

Now only one of those worked... and the reason being that under the hood the 
code is executed that i pasted in the issue (and some more but that was the 
essentials). Now in my case it's not really a problem as i want for both 
targets the same logging level, format and filters. So your merge targets 
solution is fine. I'll just make the loggingTargetClass an array of targets and 
merge them. Will be compacter and less repetition also :-)

But you might wanna consider the use case that different targets may have 
different levels, filters etc.... I can imagine that during development you 
have a traceTarget that shows much info, and an on screen display that shows 
only errors and fatals for testers. That use case is not possible in the 
current version and was possible in old versions of as3commons-logging. Of 
course up to you if you think this is useful or not :-)

Anyway, thanx for the fast answer!

Arnoud

Original comment by arno...@gmail.com on 25 Aug 2011 at 8:15

GoogleCodeExporter commented 9 years ago
It is great that you are implementing support for Spring, are you planning on 
publishing it?

RegExpSetup was designed to be a very light-weight solution to configure 
logging. It works differently from regular version but it does support Levels. 
I am not sure i am missing out on something, but I think pretty much all of 
this you mentioned is possible:

var traceT: TraceTarget = new TraceTarget();
var sosT: SOSTarget = new SOSTarget();
var both: MergedTarget = mergeTargets( traceT, sosT );

var setup: RegExpSetup = new RegExpSetup();

setup.addTargetRule( /^com\.myproject/, both );

// Exclude the targets of packA since this rule overrides the former one
setup.addTargetRule( /^com\.myproject\.packA/, null );

// To re-include the packB even though it was included in the former rule
setup.addTargetRule( /^com\.myproject\.packA\.packB/, sos );

// Fill the Debug target of the loggers for packC, all the other targets will 
stay as before and trace to sos.
setup.addTargetRule( /^com\.myproject\.packA\.packB\.packC/, traceT, 
LogSetupLevel.DEBUG_ONLY );

Its logic is different from the former solution, true but it also allows more 
flexible setups with less code.

I see that the logic (which you use to define your targets) is of a different 
nature. Maybe we should have a different setup strategy for that. What would 
you suggest?

Original comment by mastakan...@gmail.com on 25 Aug 2011 at 9:45

GoogleCodeExporter commented 9 years ago
sorry for the late reply. I was on holiday and before that a bit busy :-)

here's the basic code for the factory.

    /**
     * Factory for use in springactionscript xml config to setup and configure logging
     *
     * @example the following code configures a StringBufferTarget, filters classes and sets a log level
     *
     * <listing version="3.0">
     * <pre>
     * <object id="loggingSetup"
     *      class="x.x.util.logging.LoggingTargetFactory">
     *      <property name="loggingTargets">
     *          <array>
     *              <object class="org.as3commons.logging.setup.target.TraceTarget" />
     *              <object class="org.as3commons.logging.setup.target.AlconTarget" />
     *          </array>
     *      </property>
     *      <property value="${logging.format}" name="format" />
     *      <property value="${logging.level}" name="level" />
     *      <property name="filters">
     *          <array>
     *              <value>nl.x.x</value>
     *              <value>com.asfusion.mate</value>
     *              <value>Main</value>
     *          </array>
     *      </property>
     *  </object>
     * </pre>
     * </listing>
     *
     * @author arnoud bos
     */
    public class LoggingTargetFactory extends AbstractFactoryObject implements IInitializingObject
    {
        /** @private */
        public static const LOGGER_SETUP:RegExpSetup = new RegExpSetup();

        /** the format for the log output */
        public var format:String;

        /** log level */
        public var level:uint;

        /** the class filters */
        public var filters:Array;

        private var _loggingTargets:Array;

        /**
         * Constructs a new LoggingTargetFactoryObject instance
         */
        public function LoggingTargetFactory()
        {
            filters = [];
            loggingTargets = [];
            level = 0;

            if (LOGGER_FACTORY.setup != LOGGER_SETUP)
            {
                LOGGER_SETUP.addNoLogRule(/^org\.as3commons\.reflect\./);
                LOGGER_FACTORY.setup = LOGGER_SETUP;
            }
        }

        public function get loggingTargets():Array
        {
            return _loggingTargets;
        }

        public function set loggingTargets(value:Array):void
        {
            Assert.notNull(value, "The loggingTargets cannot be null, please check you springactionscript configuration");

            // for performance reasons we remove the trace target if we are in production
            if (! Capabilities.isDebugger)
            {
                _loggingTargets = [];
                for (var i:int = 0; i<value.length; i++)
                {
                     if (! (value[i] is TraceTarget))
                     {
                         _loggingTargets.push(value[i]);
                     }
                }
            }
            else
            {
                _loggingTargets = value;
            }
        }

        /**
         * @inheritDoc
         */
        public override function getObject():*
        {
            return LOGGER_SETUP;
        }

        /**
         * @inheritDoc
         */
        public override function getObjectType():Class
        {
            return RegExpSetup;
        }

        /**
         * Create the logging target after all properties have been set.
         */
        public function afterPropertiesSet():void
        {

            // set the format for the targets
            for (var i:int = 0; i<_loggingTargets.length; i++)
            {
                if (_loggingTargets[i] is IFormattingLogTarget)
                {
                    (_loggingTargets[i] as IFormattingLogTarget).format = format;
                }
            }

            // merge all targets
            var mergedTarget:MergedTarget = mergeTargets.apply(this, loggingTargets);

            // set the filters
            if (filters && filters.length > 0)
            {
                for (i = 0; i < filters.length; i++)
                {
                    var filter:String = filters[i] as String;

                    if (filter.indexOf('"') != -1 || filter.indexOf("'") != -1)
                    {
                        throw new Error("a filter for a log cannot have quotes!")
                    }
                    filter = filter.replace(".", "\.");
                    var regExp:RegExp = new RegExp("^" + filter, "");

                    // level setup
                    LOGGER_SETUP.addTargetRule(regExp, mergedTarget, getLogSetupLevel(level));
                }
            }
            else
            {
                // level setup
                LOGGER_SETUP.addTargetRule(/^./, mergedTarget, getLogSetupLevel(level));
            }
        }

        /**
         * get a LogSetupLevel based on a "normal" log level
         *
         * @param logLEvel the level to get the LogSetupLevel for
         */
        private function getLogSetupLevel(logLevel:uint):LogSetupLevel
        {
            if (logLevel == 0)
            {
                return LogSetupLevel.ALL;
            }
            else if (logLevel == 2)
            {
                return LogSetupLevel.DEBUG;
            }
            else if (logLevel == 4)
            {
                return LogSetupLevel.INFO;
            }
            else if (logLevel == 6)
            {
                return LogSetupLevel.WARN;
            }
            else if (logLevel == 8)
            {
                return LogSetupLevel.ERROR;
            }
            else if (logLevel == 1000)
            {
                return LogSetupLevel.FATAL;
            }
            return LogSetupLevel.ALL;
        }
    }

hope this helps!

Arnoud

Original comment by arno...@gmail.com on 21 Sep 2011 at 8:23