Class LambdaSupportLoggerProxy

java.lang.Object
de.calamanari.pk.util.LambdaSupportLoggerProxy
All Implemented Interfaces:
org.slf4j.Logger

public class LambdaSupportLoggerProxy
extends java.lang.Object
implements org.slf4j.Logger
LambdaSupportLoggerProxy is a PROXY to easier support lambda expressions as arguments to the SLF4J-Logger's logging methods.

Usage:

  • Import the defer(...)-method: import static defer(Supplier);
  • Wrap your logger: private static final Logger LOGGER = LambdaSupportLoggerProxy.wrap(LoggerFactory.getLogger(DataManager.class));
  • Use the LOGGER as usual (no interface change).
  • Whenever you need a lambda-expression to be evaluated lately, pass the lambda as an argument using defer(expression), example: LOGGER.debug("Instance of type {} found: @{}, id={}", type, defer(() -> Integer.toHexString(element.hashCode())), id);

Side Notes:

This work was part of a POC after reading through various discussions and blog-posts, for example:

I read between the lines that the fluent-API is a decent solution but many users (including me) were looking for any simpler drop-in-and-be-happy-solution.

This implementation is the best compromise I could find:

  • Minimally invasive: decision to use it or not can be made per class.
  • Lambdas can be specified on demand.
  • Simple logging statements remain clear and short, lambda-enriched statements have a still acceptable level of complexity.
  • We do not change the interface of the Logger, we do not change the existing logger usage paradigm.
  • Code analysis tools (like code helper or SonarLint) are not impacted at all.
  • The caller depth output (i.e. https://logback.qos.ch/manual/layouts.html) may change (+1) because the call to the real logger now comes from inside the PROXY.
  • The thin proxy layer adds minimal extra effort for testing all log arguments. Potentially, this may have an impact on scenarios with enabled logger and super-high throughput.
  • This solution is a trade-off between 3 factors:
    • usability: The original request was simply specifying a lambda expressions as a log argument on demand. This implementation almost satisfies this requirement as the defer()-method might be perceived as a penalty.
    • continuity: Except from the impact on the caller depth this solution is close to perfect: the user needs to do a minimal code adjustment when declaring the logger.
    • effort: Implementation effort was rather low. We accept some additional general runtime effort for argument testing.
    Another POC has shown that better usability (eliminate need for the defer()-method can be achieved by implementing an ADAPTER (generated code with a few hundred methods using argument permutation), but this would come at a high price: The implementation effort would be quite high, and we would definitely break continuity. Tests with such an adapter indicated that IDE code assist and analysis features (SonaLint) out-of-the-box won't work with the adapter in the same way they do with the plain logger. It is also questionable how IDEs react on classes with hundreds of methods. However, the runtime (evaluation) effort would be smaller because unlike the PROXY-solution the ADAPTER-implementation with argument permutation won't require any argument testing.
Author:
Karl Eilebrecht
  • Field Summary

    Fields inherited from interface org.slf4j.Logger

    ROOT_LOGGER_NAME
  • Method Summary

    Modifier and Type Method Description
    org.slf4j.spi.LoggingEventBuilder atDebug()  
    org.slf4j.spi.LoggingEventBuilder atError()  
    org.slf4j.spi.LoggingEventBuilder atInfo()  
    org.slf4j.spi.LoggingEventBuilder atTrace()  
    org.slf4j.spi.LoggingEventBuilder atWarn()  
    void debug​(java.lang.String msg)  
    void debug​(java.lang.String format, java.lang.Object arg1)  
    void debug​(java.lang.String format, java.lang.Object... arguments)  
    void debug​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void debug​(java.lang.String msg, java.lang.Throwable t)  
    void debug​(org.slf4j.Marker marker, java.lang.String msg)  
    void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)  
    void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)  
    void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void debug​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)  
    static java.lang.Object defer​(java.util.function.Supplier<?> supplier)
    This method performs a "cast" of the given supplier lambda expression to java.lang.Object to prepare it for later conditional execution by the logger.
    void error​(java.lang.String msg)  
    void error​(java.lang.String format, java.lang.Object arg1)  
    void error​(java.lang.String format, java.lang.Object... arguments)  
    void error​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void error​(java.lang.String msg, java.lang.Throwable t)  
    void error​(org.slf4j.Marker marker, java.lang.String msg)  
    void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)  
    void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)  
    void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void error​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)  
    java.lang.String getName()  
    void info​(java.lang.String msg)  
    void info​(java.lang.String format, java.lang.Object arg1)  
    void info​(java.lang.String format, java.lang.Object... arguments)  
    void info​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void info​(java.lang.String msg, java.lang.Throwable t)  
    void info​(org.slf4j.Marker marker, java.lang.String msg)  
    void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)  
    void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)  
    void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void info​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)  
    boolean isDebugEnabled()  
    boolean isDebugEnabled​(org.slf4j.Marker marker)  
    boolean isErrorEnabled()  
    boolean isErrorEnabled​(org.slf4j.Marker marker)  
    boolean isInfoEnabled()  
    boolean isInfoEnabled​(org.slf4j.Marker marker)  
    boolean isTraceEnabled()  
    boolean isTraceEnabled​(org.slf4j.Marker marker)  
    boolean isWarnEnabled()  
    boolean isWarnEnabled​(org.slf4j.Marker marker)  
    org.slf4j.spi.LoggingEventBuilder makeLoggingEventBuilder​(org.slf4j.event.Level level)  
    void trace​(java.lang.String msg)  
    void trace​(java.lang.String format, java.lang.Object arg1)  
    void trace​(java.lang.String format, java.lang.Object... arguments)  
    void trace​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void trace​(java.lang.String msg, java.lang.Throwable t)  
    void trace​(org.slf4j.Marker marker, java.lang.String msg)  
    void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)  
    void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... argArray)  
    void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void trace​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)  
    void warn​(java.lang.String msg)  
    void warn​(java.lang.String format, java.lang.Object arg1)  
    void warn​(java.lang.String format, java.lang.Object... arguments)  
    void warn​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void warn​(java.lang.String msg, java.lang.Throwable t)  
    void warn​(org.slf4j.Marker marker, java.lang.String msg)  
    void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)  
    void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)  
    void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)  
    void warn​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)  
    static LambdaSupportLoggerProxy wrap​(org.slf4j.Logger logger)
    Creates a wrapper for the underlying logger with extended interface

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • wrap

      public static LambdaSupportLoggerProxy wrap​(org.slf4j.Logger logger)
      Creates a wrapper for the underlying logger with extended interface
      Parameters:
      logger - underlying logger for delegation
      Returns:
      wrapper (enriched logger)
    • defer

      public static final java.lang.Object defer​(java.util.function.Supplier<?> supplier)
      This method performs a "cast" of the given supplier lambda expression to java.lang.Object to prepare it for later conditional execution by the logger.
      Parameters:
      supplier - lambda expression (null will be handled gracefully)
      Returns:
      supplier
    • getName

      public java.lang.String getName()
      Specified by:
      getName in interface org.slf4j.Logger
    • makeLoggingEventBuilder

      public org.slf4j.spi.LoggingEventBuilder makeLoggingEventBuilder​(org.slf4j.event.Level level)
      Specified by:
      makeLoggingEventBuilder in interface org.slf4j.Logger
    • isTraceEnabled

      public boolean isTraceEnabled()
      Specified by:
      isTraceEnabled in interface org.slf4j.Logger
    • trace

      public void trace​(java.lang.String msg)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(java.lang.String format, java.lang.Object arg1)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(java.lang.String format, java.lang.Object... arguments)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(java.lang.String msg, java.lang.Throwable t)
      Specified by:
      trace in interface org.slf4j.Logger
    • isTraceEnabled

      public boolean isTraceEnabled​(org.slf4j.Marker marker)
      Specified by:
      isTraceEnabled in interface org.slf4j.Logger
    • atTrace

      public org.slf4j.spi.LoggingEventBuilder atTrace()
      Specified by:
      atTrace in interface org.slf4j.Logger
    • trace

      public void trace​(org.slf4j.Marker marker, java.lang.String msg)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... argArray)
      Specified by:
      trace in interface org.slf4j.Logger
    • trace

      public void trace​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)
      Specified by:
      trace in interface org.slf4j.Logger
    • isDebugEnabled

      public boolean isDebugEnabled()
      Specified by:
      isDebugEnabled in interface org.slf4j.Logger
    • debug

      public void debug​(java.lang.String msg)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(java.lang.String format, java.lang.Object arg1)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(java.lang.String format, java.lang.Object... arguments)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(java.lang.String msg, java.lang.Throwable t)
      Specified by:
      debug in interface org.slf4j.Logger
    • isDebugEnabled

      public boolean isDebugEnabled​(org.slf4j.Marker marker)
      Specified by:
      isDebugEnabled in interface org.slf4j.Logger
    • debug

      public void debug​(org.slf4j.Marker marker, java.lang.String msg)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)
      Specified by:
      debug in interface org.slf4j.Logger
    • debug

      public void debug​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)
      Specified by:
      debug in interface org.slf4j.Logger
    • atDebug

      public org.slf4j.spi.LoggingEventBuilder atDebug()
      Specified by:
      atDebug in interface org.slf4j.Logger
    • isInfoEnabled

      public boolean isInfoEnabled()
      Specified by:
      isInfoEnabled in interface org.slf4j.Logger
    • info

      public void info​(java.lang.String msg)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(java.lang.String format, java.lang.Object arg1)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(java.lang.String format, java.lang.Object... arguments)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(java.lang.String msg, java.lang.Throwable t)
      Specified by:
      info in interface org.slf4j.Logger
    • isInfoEnabled

      public boolean isInfoEnabled​(org.slf4j.Marker marker)
      Specified by:
      isInfoEnabled in interface org.slf4j.Logger
    • info

      public void info​(org.slf4j.Marker marker, java.lang.String msg)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)
      Specified by:
      info in interface org.slf4j.Logger
    • info

      public void info​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)
      Specified by:
      info in interface org.slf4j.Logger
    • atInfo

      public org.slf4j.spi.LoggingEventBuilder atInfo()
      Specified by:
      atInfo in interface org.slf4j.Logger
    • isWarnEnabled

      public boolean isWarnEnabled()
      Specified by:
      isWarnEnabled in interface org.slf4j.Logger
    • warn

      public void warn​(java.lang.String msg)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(java.lang.String format, java.lang.Object arg1)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(java.lang.String format, java.lang.Object... arguments)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(java.lang.String msg, java.lang.Throwable t)
      Specified by:
      warn in interface org.slf4j.Logger
    • isWarnEnabled

      public boolean isWarnEnabled​(org.slf4j.Marker marker)
      Specified by:
      isWarnEnabled in interface org.slf4j.Logger
    • warn

      public void warn​(org.slf4j.Marker marker, java.lang.String msg)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)
      Specified by:
      warn in interface org.slf4j.Logger
    • warn

      public void warn​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)
      Specified by:
      warn in interface org.slf4j.Logger
    • atWarn

      public org.slf4j.spi.LoggingEventBuilder atWarn()
      Specified by:
      atWarn in interface org.slf4j.Logger
    • isErrorEnabled

      public boolean isErrorEnabled()
      Specified by:
      isErrorEnabled in interface org.slf4j.Logger
    • error

      public void error​(java.lang.String msg)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(java.lang.String format, java.lang.Object arg1)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(java.lang.String format, java.lang.Object... arguments)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(java.lang.String msg, java.lang.Throwable t)
      Specified by:
      error in interface org.slf4j.Logger
    • isErrorEnabled

      public boolean isErrorEnabled​(org.slf4j.Marker marker)
      Specified by:
      isErrorEnabled in interface org.slf4j.Logger
    • error

      public void error​(org.slf4j.Marker marker, java.lang.String msg)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object arg1, java.lang.Object arg2)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(org.slf4j.Marker marker, java.lang.String format, java.lang.Object... arguments)
      Specified by:
      error in interface org.slf4j.Logger
    • error

      public void error​(org.slf4j.Marker marker, java.lang.String msg, java.lang.Throwable t)
      Specified by:
      error in interface org.slf4j.Logger
    • atError

      public org.slf4j.spi.LoggingEventBuilder atError()
      Specified by:
      atError in interface org.slf4j.Logger