我使用的是最新的Eclipse和Sonar插件
日志记录的答案是:
log.debug("Request body: {}", new String(body, "UTF-8"));
只有在调试级别时才应该创建字符串:
/**
* Log a message at the DEBUG level according to the specified format
* and argument.
* <p/>
* <p>This form avoids superfluous object creation when the logger
* is disabled for the DEBUG level. </p>
*
* @param format the format string
* @param arg the argument
*/
public void debug(String format, Object arg);
但Sonar将其标记为squid:S2629
:
"前提条件"和日志参数不应要求评估(squid:S2269(
并举例说明级联
logger.log(Level.DEBUG,"出现问题:"+消息(;//不合规的;即使在日志级别过高而无法显示调试消息时也执行字符串串联
这是误报声纳警告还是我遗漏了什么?
这不是这个问题的重复,这个问题通常是关于规则概念的,它是串联的,但不是用创建对象作为new String
来格式化
另一个答案的链接说,创建new Date()
并没有产生内置格式的问题:
public static void main(String[] args) { LOGGER.info("The program started at {}", new Date()); } }
通过这种方式进行日志记录,可以避免在不应该实际记录任何内容的情况下串接的性能开销。
在非调试模式下,行
log.debug("Request body: {}", new String(body, "UTF-8"));
而不是
log.debug(MessageFormatter.format("Request body: {}", new String(body, "UTF-8")));
避免创建通过MessageFormatter.format(String messagePattern, Object arg)
创建的字符串,但不创建通过new String(body, "UTF-8")
创建的其他字符串。
这意味着它不是一个假阳性,因为参数是在调用日志记录方法之前首先计算的。
只要SLF4J不支持lambda表达式延迟求值参数,就可以使用以下实用程序方法作为解决方法:
private static Object lazyToString(final Supplier<String> stringSupplier) {
return new Object() {
@Override
public String toString() {
return stringSupplier.get();
}
};
}
这可以用于将字节数组转换为字符串限制为仅DEBUG模式:
log.debug("Request body: {}", lazyToString(() -> new String(body, StandardCharsets.UTF_8)));
虽然lambda或lazy lambda的使用很好,但仍然有好的旧isDebugEnabled
方法:
if (log.isDebugEnabled()) {
log.debug("Request body: {}", new String(body, StandardCharsets.UTF_8));
}
这不会修复正在创建的String
(因为您毕竟想显示它(,但在禁用调试模式时不会消耗内存。