展示Spring事务日志

142

我配置了带有事务支持的Spring。是否有任何方法可以记录事务,以确保我正确设置了所有内容?在日志中显示是观察发生情况的好方法。

7个回答

124

在您的log4j.properties文件中(对于其他日志记录器或log4j的xml格式,请查阅文档),您可以根据事务管理器设置spring框架的日志级别,以便获取有关事务的更多信息。例如,在使用JpaTransactionManager时,您可以进行如下设置:

log4j.logger.org.springframework.orm.jpa=INFO

(这是您事务管理器的软件包),还有

log4j.logger.org.springframework.transaction=INFO

如果 INFO 不足够,就使用 DEBUG


13
"INFO" 级别将不会显示任何交易活动,因为这会导致输出内容过于冗长。在这种情况下,需要使用 "DEBUG" 级别。 - skaffman
@Bozho,我有一个JpaTransactionManager,我想监控从池中借用连接和何时为特定事务释放连接。 - Ali
那么你需要更改连接池的日志配置。 - Bozho
如果我们使用MyBatis+SLF4J+Logback+Spring Boot会怎样? - lily

88
对我来说,一个好的日志配置是:
log4j.logger.org.springframework.transaction.interceptor = trace

它会显示类似这样的日志:
2012-08-22 18:50:00,031 TRACE - 获取 [com.MyClass.myMethod] 的事务 [来自方法 com.MyClass.myMethod 的自定义日志语句] 2012-08-22 18:50:00,142 TRACE - 完成 [com.MyClass.myMethod] 的事务

1
太好了!当你寻找这个时,不需要其他包的所有信息/调试/跟踪日志:D - Johanneke

80

对于有 application.properties 的 Spring Boot 应用程序

logging.level.ROOT=INFO
logging.level.org.springframework.orm.jpa=DEBUG
logging.level.org.springframework.transaction=DEBUG

或者如果您更喜欢Yaml (application.yaml)

logging:
   level:
      org.springframework.orm.jpa: DEBUG
      org.springframework.transaction: DEBUG

10

你也可以启用JDBC日志:

log4j.logger.org.springframework.jdbc=DEBUG

9

如果这个问题仍然涉及到JtaTransactionManager,那么JtaTransactionManager.java的最有趣的日志信息将以DEBUG优先级记录。假设您在类路径上的某个地方有一个log4j.properties文件,因此我建议使用:

log4j.logger.org.springframework.transaction=DEBUG

6

这是我在我的Logback布局实现中使用的一些代码,它派生自ch.qos.logback.core.LayoutBase

我创建了一个线程本地变量来存储对方法org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive()的引用。每当打印出新的日志行时,都会调用getSpringTransactionInfo()并返回一个将要进入日志的一个字符的字符串。

参考文献:

代码:

private static ThreadLocal<Method> txCheckMethod;

private static String getSpringTransactionInfo() {
    if (txCheckMethod == null) {
        txCheckMethod = new ThreadLocal<Method>() {
            @Override public Method initialValue() {           
                try {
                    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
                    Class<?> tsmClass = contextClassLoader.loadClass("org.springframework.transaction.support.TransactionSynchronizationManager");
                    return tsmClass.getMethod("isActualTransactionActive", (Class<?>[])null);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }                      
            }
         };    
    }
    assert txCheckMethod != null;
    Method m = txCheckMethod.get();
    String res;
    if (m == null) {
        res = " "; // there is no Spring here
    }
    else {
        Boolean isActive = null;
        try {
            isActive = (Boolean) m.invoke((Object)null);
            if (isActive) {
                res = "T"; // transaction active                    
            }
            else {
                res = "~"; // transaction inactive
            }
        }
        catch (Exception exe) {
            // suppress 
            res = "?";
        }
    }
    return res;
}

6

由于您可以在运行时访问Spring类,因此可以确定事务状态。


非常混乱,但是尝试一下:调试Spring的@Transactional注释的技巧(我自己还没有尝试过)。它使用TransactionSynchronizationManager来获取事务状态。该代码应该使用线程本地变量来缓存对isActualTransactionActive()的引用,而不是在每个日志调用中检索它。 - David Tonhofer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接