3

I am using SLF4J with Logback in a Spring Boot application. I was interested in using lazy logging and after some research, I came up with this solution.

This works as expected and does not invoke methods if the logging level is not matched.

logger.debug("Begin proceed aspect Method {} : initiator={} | recepient={} | tx_type={}",
                new Object() {@Override public String toString() { return proceedingJoinPoint.getSignature().getName(); }},
                new Object() {@Override public String toString() { return request.getAgentAlias(); }},
                new Object() {@Override public String toString() { return request.getSubscriberMobile(); }},
                new Object() {@Override public String toString() { return request.getTxType(); }});

As you can see, I am creating new Objects and overriding the toString method over and over. I don't want to do this. Is there a better way to do this?

I am using the SLF4J 1.7.28 version which came bundled with Spring Boot starter. Please note I prefer using the SLF4J over other logging frameworks.

I tried slf4j-api 2.0.0-alpha1 version along with slf4j-simple binding since it has logger.atDebug.log() implementation. But I couldn't make it work properly.

Thank you.

4 Answers4

1

If you like to add some condition lines, you could add an if statement to check if the log level is enabled and then log the message.

Lazy loading is preserved but you're going to get something like:

if(log.isDebugEnabled()) {
 log.debug(....);
}
sigur
  • 662
  • 6
  • 21
1

Better way to do that:

if (logger.isDebugEnabled()) {
    logger.debug("Begin proceed aspect Method {} : initiator={} | recepient={} | tx_type={}",
                 proceedingJoinPoint.getSignature().getName(),
                 request.getAgentAlias(),
                 request.getSubscriberMobile(),
                 request.getTxType());
}

Or:

if (logger.isDebugEnabled()) {
    logger.debug("Begin proceed aspect Method " + proceedingJoinPoint.getSignature().getName() +
                 " : initiator=" + request.getAgentAlias() +
                 " | recepient=" + request.getSubscriberMobile() +
                 " | tx_type=" + request.getTxType());
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
1

With SLF4J V2, this can also be done through the fluent API, for example: log.debug("some expensive evaluation: {}", () -> doSomethingExpensive()).

If you develop a Spring Boot app and depend on Spring for dependency management, this would mean Spring Boot 3.0 or higher as 2.x are bundled with SLF4J V1.x

Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
0

On the lines of Simas Jonelius's answer if we do not wish to change any dependencies, we could do lazy evaluation by defining suppliers for each parameter.

Supplier<String> initiator = ()-> proceedingJoinPoint.getSignature().getName();
Supplier<String> recepient = ()-> request.getAgentAlias();
Supplier<String> subscriberMobile = ()-> request.getSubscriberMobile();
Supplier<String> tx_type = ()-> request.getTxType(); ;

logger.debug("Begin proceed aspect Method {} : initiator={} | recepient={} | tx_type={}",
                initiator.get(),
                recepient.get(),
                subscriberMobile.get(),
                tx_type.get());
Sagar
  • 104
  • 1
  • 5