Spring - slf4J:如何自动记录错误和异常?

发布于 2024-10-21 18:08:22 字数 180 浏览 5 评论 0原文

我们将 Spring 与 slf4j 和 hibernate 一起使用,我试图找到一种自动记录异常和错误的方法(即无需在每个类中启动调试器的实例),以便它可以捕获任何抛出的错误或异常在日志中获取类和方法名称,

我读了一篇关于使用方面和方法的简短说明;为此拦截器,所以你能为我提供一些详细的方法来实现这一点,

问候,

We are using Spring with slf4j and hibernate, I'm trying to figure out a way to log exceptions and errors automatically (i.e without initiating an instance of the debugger in each class), so that it may catch any error or exception thrown and also get class and method name in the log,

I read a very short note about using aspects & interceptors for this, so could you provide me with some detailed way to implement this,

Regards,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

画尸师 2024-10-28 18:08:22

异常方面可能如下所示:

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

spring 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>

编辑:

如果您希望记录器代表包装的 bean 进行记录,您当然可以这样做:

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

或者如果您更喜欢此方法的声明类而不是实际的(可能代理的) /自动生成类型):

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

老实说,我无法估计每次调用 LoggerFactory.getLogger(..) 的性能影响。我认为这应该不会太糟糕,因为无论如何,例外都是例外的(即罕见的)。

an exception aspect could look like this:

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

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

if you want the logger to log on behalf of the wrapped bean, you could of course do:

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

or if you prefere the declaring class of this method rather than the actual (potentially proxied/auto-generated type):

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

Honestly, I can't estimate the performance implications of calling LoggerFactory.getLogger(..) every time. I'd assume that it shouldn't be too bad, as exceptions are exceptional (i.e. rare) anyway.

咽泪装欢 2024-10-28 18:08:22

使用纯 Aspect J(您也可以将它用于非 spring 管理的 bean)。
此示例记录服务方法“返回”的所有异常。但是您也可以更改它与其他方法匹配的切入点。

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

它是为 JUnit 编写的,但您可以轻松地适应它。

With pure Aspect J (than you can use it for not spring managed beans too).
This excample loggs all exceptions "returned" by a service method. But you can change the pointcut that it matches other methods too.

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

It is written for JUnit, but you can easely adapt it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文