Logger + Factory ?

Palleas's Avatar

Palleas

29 Sep, 2011 10:50 AM

Hi all,

I'm working on an application that just turned big enough to need a real logging solution instead of pointless trace() expressions, that's why I'll go with Flex4 's Log API which is pretty cool. As I'm not a big fan of using the static Log.getLogger('...') syntax but a big fan of dependency injection do you think it would be possible to have some kind of "custom injection rule" ?

I'd love to be able to do something like this :

package foo
{
  public class bar
  {
    [Inject]
    public var logger : ILogger; <- inject the result of Log.getLogger('foo.bar')
  }
}

Is this something doable in RL ?

Thanks,

  1. 1 Posted by mike.cann on 29 Sep, 2011 11:12 AM

    mike.cann's Avatar

    I dont use the Flex logger, I prefer to roll my own then just map my Ilogger interface as a singleton, then every time I want to log something I write:

    logger.debug(this, "This is a debug line");

    However if you want to use Flex's system I can think of a few ways you could go about this..

    One way would be to make a base class some some sort, perhaps "MyCustomActor" and have a [PostConstruct] method in there that provides you with the logger such as:

    protected var logger : ILogger;
    
    [PostConstruct]
    public function setLogger() : void
    {
        logger = Log.getLogger(getQualifiedClassName(this).split("::")[0]);
    }
    

    Another way may be to write your own injector (or extend SwiftSuspenders) so that whenever a an injection point of ILogger is found it returns the Log.getLogger() value rather than the default mapping.

    Those would be my guesses unless anyone else can thing of a cleverer solution?

    Mike

  2. Support Staff 2 Posted by Stray on 29 Sep, 2011 11:25 AM

    Stray's Avatar

    I was going to say something similar, except that I suggest you implement ILogger yourself into a delegate that can wrap the static reference rather than have to have it in your classes, which is where the inflexibility comes in. And I suggest that any 'work' should be in the wrapper implementation, not the class that uses it. (Even in a base class - sorry Mike ;P )

    This approach relies on setter injection:

    protected var _logger:ILoggerWrapper
    
    [Inject]
    public function set logger(value:ILoggerWrapper):void
    {
        _logger = value;
        _logger.setTarget(this);
    }
    

    Then you need an implementation of ILoggerWrapper that simply implements ILogger and also does this:

    protected var _logger:ILogger;
    
    public function setTarget(target:Object):void
    {
        var FQCN:String = getQualifiedClassName(target);
        // may be necessary to process the string here...
        _logger = Log.getLogger(FQCN);  
    }
    

    You'll want each instance to receive a unique instance of ILogger, so map it like this (assuming your class that does the logging activity delegating is called FlexLogWrapper):

    injector.mapClass(ILogger, FlexLogWrapper);
    

    hth,

    Stray

  3. 3 Posted by Palleas on 29 Sep, 2011 12:41 PM

    Palleas's Avatar

    I was about to use a custom injector but it seemed a too heavy solution for such a simple aim.

    Thanks, I use Stray's solution and it works great :)

    Cheers !

  4. 4 Posted by krasimir on 29 Sep, 2011 12:54 PM

    krasimir's Avatar

    Just a quick note about the subject of debugging:
    in one of my latest projects I used http://demonsterdebugger.com/ it is actually really powerful and provides nice features.

  5. 5 Posted by mike.cann on 29 Sep, 2011 01:00 PM

    mike.cann's Avatar

    Ye demonster is okay on smaller projects, try using it on anything of size and it soon chuggs however. Writing your own using sockets over localhost aint hard tho ;)

  6. Support Staff 6 Posted by Till Schneidere... on 29 Sep, 2011 01:24 PM

    Till Schneidereit's Avatar

    Just a quick update to give a narrow answer to the original question:
    The way the Swiftsuspenders injector works, it's unfortunately not
    possible to customize the injected value based on the injection
    target. Right now, that's also not possible in Swiftsuspenders 2, but
    seeing as I think that this is a very valid use-case, I will see if
    it's possible to change the injection process to enable it.

  7. 7 Posted by mike.cann on 29 Sep, 2011 01:36 PM

    mike.cann's Avatar

    Oh nice! That would be a pretty cool feature Till :)

  8. Support Staff 8 Posted by Till Schneidere... on 29 Sep, 2011 01:52 PM

    Till Schneidereit's Avatar

    I'll see what I can do :)

  9. Support Staff 9 Posted by Till Schneidere... on 29 Sep, 2011 04:10 PM

    Till Schneidereit's Avatar

    Good news: I just prototyped (or, in fact implemented without much
    testing) the required changes and it looks like the overhead is
    negligible. That means that in Swiftsuspenders 2, all dependency
    providers will have access to the target object's class. They can't
    have access to the actual instance though, because in case of
    constructor injection, the instance won't be created at the time of
    dependency collection.

    On Thu, Sep 29, 2011 at 15:51, Till Schneidereit
    <[email blocked]> wrote:
    > I'll see what I can do :)
    >
    > On Thu, Sep 29, 2011 at 15:36, Mike Cann
    > <[email blocked]>
    > wrote:
    >>

  10. 10 Posted by Stray on 29 Sep, 2011 04:17 PM

    Stray's Avatar

    Nice work sir! That's very good news - an extra flexible feature based on a real use case :)

  11. 11 Posted by mike.cann on 29 Sep, 2011 04:25 PM

    mike.cann's Avatar

    Agreed! Nice work Till :)

  12. 12 Posted by Palleas on 30 Sep, 2011 12:58 PM

    Palleas's Avatar

    I think I'm in love with Till.

    Thank you :)

  13. 13 Posted by Stray on 30 Sep, 2011 01:25 PM

    Stray's Avatar

    It's impossible not to be at least a little bit in love with Till.

    xx

  14. Support Staff 14 Posted by Till Schneidere... on 30 Sep, 2011 02:16 PM

    Till Schneidereit's Avatar

    Now let's not get ahead of ourselves: It's logging we're talking about, here ;)

    In other news, I've just pushed the required changes to the branch that will become Swiftsuspenders 2:
    https://github.com/tschneidereit/SwiftSuspenders/tree/the-future

    Once that's released, writing a provider encapsulating Log.getLogger will boil down to this:

    package com.example.injectionproviders
    {
        import flash.utils.getQualifiedClassName;
    
        import mx.logging.Log;
    
        import org.swiftsuspenders.Injector;
        import org.swiftsuspenders.dependencyproviders.DependencyProvider;
    
        public class LoggerProvider implements DependencyProvider
        {
            public function apply(targetType : Class, activeInjector : Injector) : Object
            {
                return Log.getLogger(getQualifiedClassName(targetType));
            }
        }
    }
    

    Using it will look like this:

    injector.map(ILogger).setProvider(LoggerProvider);
    

    (Don't you just love the brevity of AS3? A LOC/ lines-that-actually-do-something ratio of 10:1, yay!)

  15. 15 Posted by Palleas on 30 Sep, 2011 02:30 PM

    Palleas's Avatar

    The syntax is really cool.

  16. Support Staff 16 Posted by Ondina D.F. on 01 Nov, 2011 02:13 PM

    Ondina D.F.'s Avatar

    If you need more help with this, please feel free to re-open this discussion. Please open new threads for new issues.
    Thanks!
    Ondina

  17. Ondina D.F. closed this discussion on 01 Nov, 2011 02:13 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac