139

I configured spring with transactional support. Is there any way to log transactions just to ensure I set up everything correctly? Showing in the log is a good way to see what is happening.

praseodym
  • 2,134
  • 15
  • 29
cometta
  • 35,071
  • 77
  • 215
  • 324

7 Answers7

124

in your log4j.properties (for alternative loggers, or log4j's xml format, check the docs)

Depending on your transaction manager, you can set the logging level of the spring framework so that it gives you more info about transactions. For example, in case of using JpaTransactionManager, you set

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

(this is the package of the your transaction manager), and also

log4j.logger.org.springframework.transaction=INFO

If INFO isn't enough, use DEBUG

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 13
    `INFO` level won't show any tx activity at all, it would be too verbose. `DEBUG` will be necessary there. – skaffman Dec 27 '09 at 11:03
  • @Bozho I've JpaTransactionManager and I wanna monitor when a connection is borrowed from pool and when it was release for a specific transaction. – Ali Jun 04 '13 at 18:31
  • then you'd need to change the logging configuration for your connection pool – Bozho Jun 05 '13 at 08:56
  • what if we use mybatis+slf4j+logback+springboot? – lily Oct 15 '19 at 09:23
88

For me, a good logging config to add was:

log4j.logger.org.springframework.transaction.interceptor = trace

It will show me log like that:

2012-08-22 18:50:00,031 TRACE - Getting transaction for [com.MyClass.myMethod]

[my own log statements from method com.MyClass.myMethod]

2012-08-22 18:50:00,142 TRACE - Completing transaction for [com.MyClass.myMethod]

moffeltje
  • 4,521
  • 4
  • 33
  • 57
Sander S.
  • 881
  • 6
  • 2
  • 1
    Great! No need to have all the info/debug/trace logging of other packages, when this is what you're looking for :D – Johanneke Feb 18 '15 at 13:23
78

For Spring Boot application with application.properties

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

or if you prefer Yaml (application.yaml)

logging:
   level:
      org.springframework.orm.jpa: DEBUG
      org.springframework.transaction: DEBUG
MariuszS
  • 30,646
  • 12
  • 114
  • 155
10

You could enable JDBC logging as well:

log4j.logger.org.springframework.jdbc=DEBUG
Pep
  • 101
  • 1
  • 2
9

Most interesting log informations of JtaTransactionManager.java (if this question is still about the JtaTransactionManager) are logged at DEBUG priority. Assuming you have a log4j.properties somewhere on the classpath, I'd thus suggest to use:

log4j.logger.org.springframework.transaction=DEBUG
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
6

Because you can access Spring classes at runtime, you can determine transaction status.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Michel Gokan Khan
  • 2,525
  • 3
  • 30
  • 54
  • Very broken, but try: [Tips for Debugging Spring's @Transactional Annotation](http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/) (haven't tried it myself yet). It uses [TransactionSynchronizationManager](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationManager.html) to get transaction status. The code should probably use a thread-local variable to cache the reference to the `isActualTransactionActive()` instead of retrieving it on each logging call. – David Tonhofer Oct 07 '17 at 16:17
6

Here is some code I use in my Logback Layout implementation derived from ch.qos.logback.core.LayoutBase.

I create a thread-local variable to store the reference to the method org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive(). Whenever a new log line is printed out, getSpringTransactionInfo() is called and it returns a one-character string that will go into the log.

References:

Code:

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;
}
David Tonhofer
  • 14,559
  • 5
  • 55
  • 51