当您拥有的价值高于计算成本时,您在日志记录框架中看到的常见模式是
if (log.isDebugEnabled()) {
String value = expensiveComputation();
log.debug("value: {}", value);
}
由于Java 8添加了lambda,所以这样做很好:
log.debug("value: {}", (Supplier<String>) this::expensiveComputation);
哪个几乎有效,因为日志记录框架会对参数执行toString()
。问题是toString()
Supplier
是Object
中的实现。
有没有办法提供一些懒惰地评估Logger
方法的东西?它几乎只是一个Supplier
,默认toString()
调用get()
。
答案 0 :(得分:6)
要传递将以惰性方式执行String
计算的参数,您必须传递Supplier
而不是String
。
您调用的方法应具有以下签名:
void debug(Supplier<?> msgSupplier, Throwable t)
您可以在自己的实用程序类中引入此实用程序方法
但您不应该这样做,因为最近的日志记录框架(如Log4j2)提供了开箱即用的功能。
例如,org.apache.logging.log4j.Logger提供了重载方法来记录接受Supplier
对于example:
void debug(MessageSupplier msgSupplier, Throwable t)
记录消息(仅在记录级别为时才构建) DEBUG级别)包括传递给Throwable的堆栈跟踪 参数。 MessageSupplier可能使用也可能不使用MessageFactory 构建消息。
Parameters
:
msgSupplier
- 一个函数,在调用时会生成所需的日志 消息。
t
- 记录的异常,包括其堆栈跟踪。
来自Log4j2文档:
Java 8 lambda支持延迟日志记录
在2.4版中,Logger界面增加了对lambda的支持 表达式。这允许客户端代码懒惰地记录消息 显式检查是否启用了请求的日志级别。对于 例如,以前你会写:
if (logger.isTraceEnabled()) { logger.trace("Some long-running operation returned {}", expensiveOperation()); }
使用Java 8,您可以使用lambda表达式实现相同的效果。 您不再需要显式检查日志级别:
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
答案 1 :(得分:5)
一个小帮手对象可以让你做你想做的事情:
public class MessageSupplier {
private Supplier<?> supplier;
public MessageSupplier(Supplier<?> supplier) {
this.supplier = supplier;
}
@Override
public String toString() {
return supplier.get().toString();
}
public static MessageSupplier msg(Supplier<?> supplier) {
return new MessageSupplier(supplier);
}
}
然后,静态导入msg
:
log.debug("foo: {}", msg(this::expensiveComputation));
答案 2 :(得分:1)
哪个几乎有效,因为日志框架会对参数执行
toString()
。
此声明不正确。如果您进入debug
/ info
/无论采用何种方式,您都会找到此实施方式:
public void log(Level level, Supplier<String> msgSupplier) {
if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
doLog(lr);
}
如果level
未满足,则Supplier
甚至无法使用。
答案 3 :(得分:1)
有趣的是,你甚至不能使用这样的东西
interface LazyString {
String toString();
}
作为功能界面
到目前为止,我找到的唯一方法是通过匿名课程。
Object o = new Object() {
@Override
public String toString() {
return myExpensiveComputation();
}
};
System.out.printf("%s", o);
答案 4 :(得分:0)
对于java.util.logging
和Java 8+,您还可以使用以下 lazy 和方便的符号:
LOGGER.fine(() -> "Message1: " + longComputation1() + ". Message2: " + longComputation2());
longComputation1()
和longComputation2()
将被称为惰性-即仅在需要时使用。