2011-03-15 16 views
5

Usiamo Spring con slf4j e hibernate, sto cercando di capire un modo per registrare eccezioni ed errori automaticamente (cioè senza avviare un'istanza del debugger in ogni classe), in modo che possa rilevare qualsiasi errore o eccezione lanciata e anche ottenere di classe e metodo di nome nel registro,Spring - slf4J: come registrare automaticamente errori ed eccezioni?

ho letto una breve nota su come utilizzare gli aspetti & intercettori per questo, così mi può fornire qualche modo dettagliato per implementare questo,

Saluti,

+0

Cosa otterrebbe ciò che non si possiede già da una traccia stack? Se pianifichi di loggare e ingoiare l'eccezione attraverso gli aspetti, mi sembra una pessima idea. –

risposta

10

un aspetto di eccezione potrebbe essere il seguente:

@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:

se si desidera che il registratore per registrare per conto del fagiolo avvolto, si potrebbe ovviamente fare:

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

o se preferisci la classe dichiarante di questo metodo piuttosto che il tipo effettivo (potenzialmente con proxy/auto-generato):

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

Onestamente, non posso stimare le implicazioni di prestazione di chiamare LoggerFactory.getLogger (..) ogni volta. Suppongo che non dovrebbe essere troppo cattivo, come eccezioni sono eccezionali (vale a dire raro) in ogni caso.

+0

La tua risposta è estremamente chiara, ma cosa succede se voglio che il logger esegua il login con il nome della classe chiamante, non con il nome della mia classe di aspetto? –

+0

@Amr vedi "MODIFICA:" – sfussenegger

+0

La tua risposta è appena migliorata, hai anche menzionato il problema delle prestazioni, che sto anche pensando, Grazie mille –

0

Con puro Aspetto J (che si può usare anche per i fagioli non gestiti a molla). Questo esempio registra tutte le eccezioni "restituite" da un metodo di servizio. Ma puoi cambiare il punto di taglio che corrisponde anche ad altri metodi.

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);   
    } 
} 

È scritto per JUnit, ma è possibile easely adattarlo.

Problemi correlati