我们已经迁移了所有代码以使用slf4 API来使用通用API,但是现在我们正在考虑从log4j 1.x升级到log4j 2.x.如果我们使用slf4j API和log4j2作为实现,我们能否使用log4j2的所有功能?
答案 0 :(得分:40)
Log4j2 API比SLF4J API更丰富,许多Log4j2 API功能不可通过SLF4J访问。请参阅下文了解详情。
Log4j2实现的功能,如异步记录器,查找,过滤器,布局和附加程序,可通过配置进行控制,无论您在应用程序中使用何种日志API,都可以使用。
另请参阅此answer以了解为什么安全地编程到Log4j2 API 的不同但相关的问题。
SLF4J中没有10个Log4j2 API功能
(1)Message API允许应用程序除了文本之外还记录结构化对象。在内部,Log4j2将记录到消息的所有内容转换为API,并将其公开给API,为应用程序与下游日志记录组件(过滤器,布局,追加器)进行交互提供了各种可能性。如果您将自定义组件开发为Log4j2的插件,以及使用内置组件时,这可能很有用。有关内置示例,请参阅StructuredDataMessage如何用于Rfc5424Layout的细粒度控制。
(2)Java 8 lambda support允许您懒惰地创建参数或日志消息,而无需显式检查是否启用了请求的日志级别。
// Java-8 style optimization: no need to explicitly check the log level:
// the lambda expression is not evaluated if the TRACE level is not enabled
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
(3)使用String :: format %s %d
样式参数混合{}样式参数。 {}样式具有更好的性能,可以与任何参数类型一起使用,但printf
样式可以对格式进行细粒度控制。 Log4j2允许您轻松混合这些参数样式。例如:
logger.debug("Opening connection to {}...", someDataSource);
logger.printf(Level.INFO, "Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
(4)CloseableThreadContext为SLF4J中的普通ThreadContext(MDC)提供了一些额外的便利:它会在您完成后自动删除项目。例如:
// Add to the ThreadContext map for this try block only;
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext
.put("id", UUID.randomUUID().toString())
.put("loginId", session.getAttribute("loginId"))) {
logger.debug("Message 1");
// call some other code that also does logging
...
logger.debug("Message 2");
...
} // "id" and "loginId" are now removed from the ThreadContext map
(5)除了键值对之外,Log4j2的ThreadContext还具有push
和pop
方法来支持堆栈功能(以前在Log4j 1中称为NDC)
(6)SLF4J不支持FATAL日志级别。
(7)Log4j2支持custom log levels。这些方法可以与log
方法一起使用,例如:logger.log(Level.getLevel("FINE"), "... msg")
,或者您可以使用自定义日志级别的便捷方法生成自定义记录器包装器。
(8)Log4j2 API接受任何Object,而不仅仅是字符串。这是允许Log4j2为“garbage-free”的事情之一,这意味着它将避免分配新对象。如果它是Number,CharSequence或实现(Log4j2)StringBuilderFormattable接口,则会记录您的Object而不创建任何临时字符串。
如果记录10个或更少的参数,Log4j2 API也将避免创建vararg数组。如果您记录的参数超过2个,SLF4J会创建vararg数组。
(9)以上是直接使用Log4j2 API免费获得的。最重要的是,如果你真的关心避免创建临时对象(比如一些交互式游戏和低延迟金融应用程序),你可以避免使用Unbox实用程序类自动装箱原始参数。
(10)SLF4J Markers使用粗粒度同步可能会对多线程应用程序(SLF4J-240)产生性能影响。请参阅此performance test results页面的“高级过滤”部分。
免责声明:我参与了Log4j2。