如果我们将它与slf4j api一起使用,我们可以使用log4j2的所有功能吗?

问题描述 投票:16回答:1

我们已经迁移了所有代码以使用slf4 API来使用通用API,但是现在我们正在考虑从log4j 1.x升级到log4j 2.x.如果我们使用slf4j API和log4j2作为实现,我们是否能够使用log4j2的所有功能?

java logging log4j slf4j log4j2
1个回答
40
投票

Log4j2 API比SLF4J API更丰富,并且无法通过SLF4J访问许多Log4j2 API功能。请参阅下文了解详情。

Log4j2实现的功能(如异步记录器,查找,过滤器,布局和附加器)通过配置进行控制,无论您在应用程序中使用何种日志API,都可以使用它们。

另请参阅此answer以了解为何可以安全地编程到Log4j2 API的相关问题。

10 SLF4J中没有Log4j2 API功能

(1)Message API允许应用程序除了文本之外还记录结构化对象。在内部,Log4j2将记录到消息的所有内容转换为API,并将其公开给API,为应用程序与下游日志记录组件(过滤器,布局,追加器)进行交互提供了各种可能性。如果您将自定义组件开发为Log4j2的插件,以及使用内置组件时,这可能很有用。有关内置示例,请参阅如何使用StructuredDataMessageRfc5424Layout进行细粒度控制。

(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样式参数混合{} -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还具有支持堆栈功能的pushpop方法(以前在Log4j中称为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做出贡献。

© www.soinside.com 2019 - 2024. All rights reserved.