2011-03-15 16 views
5

Estamos usando Spring con slf4j e hibernate, estoy tratando de encontrar una forma de registrar excepciones y errores automáticamente (es decir, sin iniciar una instancia del depurador en cada clase), para que pueda detectar cualquier error o excepción lanzada y también obtener la clase y el método de nombre en el registro,Spring - slf4J: ¿cómo registrar automáticamente errores y excepciones?

leí una nota muy poco sobre el uso de los aspectos & interceptores de este, por lo que podría proveer de mí de alguna manera detallada para implementar esto,

Saludos,

+0

¿Qué significaría esto que aún no tiene de un rastro de pila? Si planeas iniciar sesión y tragar la excepción a través de aspectos, eso me parece una idea bastante mala. –

Respuesta

10

un aspecto de excepción podría verse así:

@Aspect 
public class ExceptionAspect { 

    private static final Logger log = LoggerFactory.getLogger(ExceptionAspect.class); 

    public Object handle(ProceedingJoinPoint pjp) throws Throwable { 
    try { 
     return pjp.proceed(); 
    } catch (Throwable t) { 
     // so something with t: log, wrap, return default, ... 
     log.warn("invocation of " + pjp.getSignature().toLongString() + " failed", t); 
     // I hate logging and re-raising, but let's do it for the sake of this example 
     throw t; 
    } 
    } 
} 

primavera conf:

<!-- log exceptions for any method call to any object in a package called 'svc' --> 
<bean class="org.example.aspects.ExceptionAspect" name="exceptionAspect" /> 
<aop:config> 
    <aop:aspect ref="exceptionAspect"> 
    <aop:around method="handle" pointcut="execution(* org.example..svc..*.*(..))" /> 
    </aop:aspect> 
</aop:config> 

EDIT:

si desea que el registrador para iniciar la sesión en nombre del grano envuelto, usted podría, por supuesto, hacer:

LoggerFactory.getLogger(pjp.getTarget().getClass()).warn("damn!"); 

o si Prefiere la clase de declaración de este método en lugar de la real (potencialmente proxiado/tipo autogenerado):

LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()).warn("damn!"); 

Honestamente, no puedo estimar las implicaciones de rendimiento de llamar a LoggerFactory.getLogger (..) cada vez. Supongo que no debería ser tan malo, ya que las excepciones son excepcionales (es decir, raras) de todos modos.

+0

Su respuesta es extremadamente clara, pero ¿qué ocurre si quiero que el registrador inicie sesión con el nombre de la clase llamante, no con mi nombre de clase de aspecto? –

+0

@Amr ver "EDITAR:" – sfussenegger

+0

Su respuesta es cada vez mejor, también mencionó el problema de rendimiento, que también estoy pensando, muchas gracias –

0

Con aspecto puro J (que puede usarlo también para los granos administrados por resorte). Este ejemplo registra todas las excepciones "devueltas" por un método de servicio. Pero puede cambiar el punto de corte que coincida con otros métodos también.

package test.infrastructure.exception; 

import java.util.Arrays; 

import org.apache.log4j.*; 
import org.aspectj.lang.Signature; 
import org.springframework.stereotype.Service; 

/** Exception logger*/ 
public aspect AspectJExceptionLoggerAspect { 

    /** The name of the used logger. */ 
    public final static String LOGGER_NAME = "test.infrastructure.exception.EXCEPTION_LOGGER"; 

    /** Logger used to log messages. */ 
    private static final Logger LOGGER = Logger.getLogger(LOGGER_NAME); 

    AspectJExceptionLoggerAspect() { 
    } 

    /** 
    * Pointcut for all service methods. 
    * 
    * Service methods are determined by two constraints: 
    * <ul> 
    * <li>they are public</li> 
    * <li>the are located in a class of name *SericeImpl within (implement an interface) 
    * {@link test.service} package</li> 
    * <li>they are located within a class with an {@link Service} annotation</li> 
    * </ul> 
    */ 
    pointcut serviceFunction() 
     : (execution(public * test.Service.*.*ServiceImpl.*(..))) 
     && (within(@Service *)); 

    /** Log exceptions thrown from service functions. */ 
    after() throwing(Throwable ex) : serviceFunction() { 
     Signature sig = thisJoinPointStaticPart.getSignature(); 
     Object[] args = thisJoinPoint.getArgs(); 

     String location = sig.getDeclaringTypeName() + '.' + sig.getName() + ", args=" + Arrays.toString(args); 
     LOGGER.warn("exception within " + location, ex);   
    } 
} 

Está escrito para JUnit, pero se puede acoger cómodamente adaptarlo.

Cuestiones relacionadas