Results 1 to 5 of 5

Thread: How can one inject a logger?

  1. #1
    Join Date
    Apr 2008
    Posts
    9

    Question How can one inject a logger?

    I'm trying to put in place a high-level exception/logging library. I started out using the Spring.Aspects.Exceptions.ExceptionHandlerAdvice class, but it doesn't seem to have the flexibility hinted at in the docs, so this didn't work:

    Code:
    <object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
    				<property name="exceptionHandlers">
    					<list>
    						<value>on exception name NullReferenceException log(Debug,"logger")</value>
    					</list>
    				</property>
    			</object>
    So, I just created my own advice class. However, I'd like to be able to inject a particular logger into it. This doesn't seem to work:

    Code:
    <object id="UnhandledExceptionAdvice" type="ISI.HDS.Diagram.Deployer.UnhandledExceptionAdvice, ISI.HDS.Diagram.Deployer" lazy-init="true">
    				constructor-arg expression="LogManager.GetLogger('logger')"></constructor-arg>
    			</object>
    Does anyone know of a way? Alternatively, does anyone know how to configure Spring.Aspects.Exceptions.ExceptionHandlerAdvice to log using different priorities/levels (e.g. Debug, Information)? The documentation says it defaults to Debug.

  2. #2
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    Hi 3-eye,

    The exception handling advice doesn't support that feature at the moment. I've added a JIRA issue to keep track of it. We will get a fix out much before the next release, I'll ping back here once it is done.

    I've attached a solution with a few options. You'll need to copy supporting .dlls into the lib directory.

    The first option is a copy of the existing implementation of ExceptionHandlerAdvice with a simple improvement that will let you configure the logging level used with the log action. (Unfortunately some methods I would have liked to override were private and not protected, I'll fix that as well so in the future you could subclass).

    With the updated code you can configure the log level for all logging actions as shown below

    Code:
      <object name="exceptionHandlingAdvice" type="LoggingExample.Aspects.Exceptions.ExceptionHandlerAdvice, LoggingExample">
        <property name="LogMethod" value="Info"/>
        <property name="exceptionHandlers">
          <list>
             ...
          </list>
        </property>
      </object>
    The expression syntax you used didn't work because you need to register a type alias for LogManager. The following bits of xml in App.config will do this for you.
    Code:
      <configSections>
           <sectionGroup name="spring">
               <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
               <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
               <section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/>
           </sectionGroup>
      </configSections>
    
      <spring>
      <context>
               <resource uri="assembly://LoggingExample/LoggingExample/application-config.xml"/>
           </context>
    
           <parsers>
               <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
           </parsers>
    
           <typeAliases>
              <alias name="LogManager" type="Common.Logging.LogManager, Common.Logging"/>
           </typeAliases>
     </spring>
    Another option is to 'sneak' in some logging when you are performing exception translation. You can list multiple expressions (expression lists) to be evaluated, one of which could be a custom logging action. You need to enclose the multiple SpEL statement with parenthesis and separate each one with a semicolon. Here is an example configuration

    Code:
      <object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
        <property name="exceptionHandlers">
          <list>
            <value>on exception name ArithmeticException translate ( @(logHelper).LogException('Mylogger', LogLevel.Error, 'exception occured', #e); new System.ArithmeticException('wrapped bad math', #e) )</value>
          </list>
        </property>
      </object>
    The '@' syntax retrieves a spring managed object by name from the container.

    If you want to go the route of using your own logging advice, you might want to consider using Spring's SimpleLoggingAdvice class. This class is 'subclass' friendly and should take care of much of the grunt work in implementing your own logging advice.

    Cheers,
    Mark
    Attached Files Attached Files
    Last edited by Mark Pollack; 06-09-2008 at 06:05 PM. Reason: xml formatting

  3. #3
    Join Date
    Apr 2008
    Posts
    9

    Default

    Hi Mark,

    Thanks for the thorough answer, explanation, and even sample code. That's what I call real support!

    I do have to ask, though, are you sure you want to make log level a property of the advice, rather than part of the exceptionHandlers? I could see the possibility of different log levels for different exceptions, all handled by one advice, such as

    Code:
    <object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
    				<property name="exceptionHandlers">
    					<list>
    						<value>on exception name NullReferenceException log(Error,"logger") "hi dudes"</value>
    						<value>on exception name Exception log(Fatal,"logger") "Woah dudes"</value>
    					</list>
    				</property>
    			</object>
    Granted, one could set up multiple advisors, theoretically, but that seems like something that shouldn't be forced on the developer.

  4. #4
    Mark Pollack is offline Spring.NET Co-Lead Spring TeamSpring User
    Join Date
    Sep 2004
    Location
    New York, NY
    Posts
    1,683

    Default

    Hi,

    I also had the same concerns. I worked on it a bit more and put those properties in the handler so as not to complicate the 'action' part of the DSL with additional parameters. These additional parameter would need to be configured by passing values through the ExceptionHandlerAdvice to the log handler. That feels a bit wrong though the advice is responsible for actually 'new'-ing the handle instance so perhaps it is fine for configuration of the level and type for the 'simple' log action.

    There are two changes to make in this class. One has already been done, namely to let you pass in an instance of IExceptionHandler, see SPRNET-942 for an example.

    The other change is to introduce a new action called execute, this would allow you to write something like this.
    Code:
      <object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
        <property name="exceptionHandlers">
          <list>
            <value>on exception name ArithmeticException execute @(logHelper).LogException('Mylogger', LogLevel.Error, 'exception occured', #e)</value>
          </list>
        </property>
      </object>
    or

    Code:
    on exception name ArithmeticException execute LogManager.GetLogger("MyLoggerName").Trace('My Message',#e)
    As with the logging handler, other handlers in the chain would still be called after the execute handler is invoked. This seems better than adding additional options into the log action, i.e. log(LogLevel.Debug, "MyLoggerName", true). The last option would decide if you call log.debug("message", e), i.e. with or without the exception. Might as well let people use the API naturally and also give people the opportunity to call other apis.

    What do you think?

    Cheers,
    Mark
    Last edited by Mark Pollack; 06-12-2008 at 11:34 AM. Reason: minor changes.

  5. #5
    Join Date
    Apr 2008
    Posts
    9

    Default

    [sorry it's taken a while to get back to this.]

    I definitely like the idea of the execute action. That opens the door completely, without feeling like one is sneaking anything in. I also like the approach in SPRNET-942, which basically opens the door just as widely, although with more verbose semantics.

    I haven't dived into the source code, so I can't really give you the best response at this time, but I think this direction is better than the previous. You kind of remind me of myself (if you don't mind the insult) in putting one sort of contract and implementation out there and then quickly switching it out for another (hopefully improved).

    One final note, though. If the log action is going to remain limited to Debug level, then it's power and usefulness is severely limited. In fact, I don't see why I'd use it at all in production (asuuming the above changes are available to me). However, the priority to me would be to extend the functionality in whatever way seems best, and if that means leaving the log action weak for now, or even forever, that's fine, because if a thing serves my needs well via one configuration, it's not that important that the same need isn't served in another that was even perhaps designed to in the beginning. Maybe eventually the log action can be improved, but obviously it's the high-value targets that have to be aimed for first. SPRNET-942 seems like perhaps the highest value target here.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •