47

In Log4j latest API we have Lambda support where I can manage the Debug option easily.

Example:

logger.debug("This {} and {} with {} ", 
  () -> this, () -> that, () -> compute());

But for slf4j/logback is there any option to have lambda enabled as mentioned above. Please let me know the syntax then.

Souvik
  • 1,219
  • 3
  • 16
  • 38

5 Answers5

18

SLF4J – version 2

Version 2 of SLF4J has support for lambda syntax. This new version also brings a fluent API.

Version 2 is now the current generation of SLF4J. Latest release is 2.0.6 as of 2023-01. Requires Java 8 or later.

Maven POM setting:

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.6</version>
</dependency>

See the Download page. See this repository.

Askar Kalykov
  • 2,553
  • 1
  • 22
  • 43
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
16

Unfortunately, this is not supported yet: https://jira.qos.ch/browse/SLF4J-371

Mariano Ruiz
  • 4,314
  • 2
  • 38
  • 34
9

slf4j-lambda supports that:

import kr.pe.kwonnam.slf4jlambda.LambdaLogger;
import kr.pe.kwonnam.slf4jlambda.LambdaLoggerFactory;

LambdaLogger log = LambdaLoggerFactory.getLogger(YourClass.class);

// lambda for message itself
log.debug(() -> createMessage("debug level"));

// lambda for message format's arguments
log.info("info lambda formatter number {}, string {}", () -> 123, () -> "Hello LambdaLogger");

// method reference
public String longRunnigMethod() {
    return "some long running method";
}

log.debug("Long running method logging {}", this::longRunnigMethod);

// exception logging
log.error(() -> "error lambda exception msg - " + ex.getMessage(), ex);
koppor
  • 19,079
  • 15
  • 119
  • 161
  • 7
    @downvoters Please leave a comment why you dislike this answer. Is it because you don't want to add another library or because this library currently has 7 stars on GitHub only? – koppor Mar 29 '18 at 07:47
  • 10
    Because we don't want more dependencies in logging libs zoo. There is a request to support lambdas in slf4j(https://jira.qos.ch/browse/SLF4J-371) and there is already such feature in log4j. Please, rather than create another lib, propose a pull request in slf4j. – Mr. Cat Apr 10 '18 at 15:22
  • 7
    @Mr.Cat Please approach the author of the lib and/or take the code and integrate it in slf4j. Double check the license before – koppor Apr 10 '18 at 16:36
  • 4
    https://jira.qos.ch/browse/SLF4J-371 has been sitting there since 2016. Old discussion here http://slf4j.42922.n3.nabble.com/Lambda-support-in-SLF4J-td4026483.html. – tkruse Aug 09 '18 at 01:10
4

Maybe something like this would work. You'll need to determine if the cost of new'ing instances is better than doing it another way.

logger.debug("This {} and {} with {} ",
    defer(() -> this),
    defer(() -> that),
    defer(() -> compute()));

Then with this...

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor(staticName = "defer")
public class LogString {
    @NonNull private final StringGenerator generator;

    @Override
    public String toString() {
        return generator.createString();
    }

    public interface StringGenerator {
        String createString();
    }
}
TJR
  • 3,617
  • 8
  • 38
  • 41
  • 2
    Does this actually defer the execution if the debug level isn't set? I believe the JVM will in fact invoke the defer() method which will invoke the lambda. Maybe you could put a branch in there to check the log level – Jonathan S. Fisher Aug 15 '18 at 19:07
  • 1
    Don't take my word for it. Try it out and test it. :) – TJR Aug 16 '18 at 20:23
  • @JonathanS.Fisher `defer` will be invoked and return a LogString object. The lambda will not be invoked (it's a lambda, not an expression!). Only if the debug level is set and slf4j calls LogString::toString, will the lambda execute. – Aleksandr Dubinsky Oct 21 '18 at 16:01
  • Unfortunately this trick creates extra object on stack (`LogString` with factory `LogString.defer()`). – gavenkoa Dec 27 '21 at 21:52
  • 1
    @gavenkoa Hence the poster's comment about "You'll need to determine if the cost ..." because if `compute()` is expensive, it still may be worth it – Stewart Jul 01 '22 at 20:51
4

As of August 20th SLF4j version 2.0 was released with support for lambdas.

Currently only the newly added optional fluent API supports lambdas. They can also be combined with traditional variable parameters. See the following example:

logger.atDebug().setMessage("Temperature set to {}. Old value was {}.").addArgument(() -> someSupplier()).addArgument(oldT).log();

Reference: SLF4J Manual - Fluent

Zhnz
  • 45
  • 1
  • 4