我们已经迁移了所有代码以使用slf4 API来使用通用API,但是现在我们正在考虑从log4j 1.x升级到log4j 2.x. 如果我们使用slf4j API和log4j2作为实现,我们是否能够使用log4j2的所有功能?
Log4j2 API比SLF4J API更丰富,并且无法通过SLF4J访问许多Log4j2 API功能.请参阅下文了解详情.
Log4j2实现的功能(如异步记录器,查找,过滤器,布局和附加器)通过配置进行控制,无论您在应用程序中使用何种日志API,都可以使用它们.
另请参阅这个答案,以解答为什么安装Log4j2 API是安全的不同但相关的问题.
10 SLF4J中没有Log4j2 API功能
(1)Message API允许应用程序除了文本之外还记录结构化对象.在内部,Log4j2将记录到消息的所有内容转换为API,并将其暴露给API,为应用程序与下游日志记录组件(过滤器,布局,追加器)进行交互提供了各种可能性.如果您将自定义组件开发为Log4j2的插件,以及使用内置组件时,这可能很有用.有关内置示例,请参阅StructuredDataMessage如何用于对Rfc5424Layout进行细粒度控制.
(2)Java 8 lambda支持允许您懒惰地创建参数或日志消息,而无需显式检查是否启用了请求的日志级别.
// 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
-style参数混合{} -style参数.{}样式具有更好的性能,可以与任何参数类型一起使用,但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支持自定义日志级别.这些可以与log
方法一起使用,例如:logger.log(Level.getLevel("FINE"), "... msg")
,或者您可以使用自定义日志级别的便捷方法生成自定义记录器包装器.
(8)Log4j2 API接受任何Object,而不仅仅是字符串.这是允许Log4j2"无垃圾 "的事情之一,这意味着它将避免分配新的对象.如果它是Number,CharSequence或实现(Log4j2)StringBuilderFormattable接口,则会记录您的Object而不创建任何临时字符串.
如果您记录10个或更少的参数,Log4j2 API也将避免创建vararg数组.如果您记录的参数超过2个,SLF4J会创建vararg数组.
(9)以上是直接使用Log4j2 API免费获得的.最重要的是,如果你真的关心避免创建临时对象(比如一些交互式游戏和低延迟金融应用程序),你可以避免使用Unbox实用程序类自动装箱原始参数.
(10)SLF4J Markers使用粗粒度同步可能会对多线程应用程序(SLF4J-240)产生性能影响.请参阅此性能测试结果页面的"高级筛选"部分.
免责声明:我为Log4j2做出贡献.