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

Can we use all features of log4j2 if we use it along with slf4j api?

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

Log4j2 API 比 SLF4J API 更丰富,许多 Log4j2 API 功能不能 通过 SLF4J 访问。详情见下文。

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

另请参阅此 以解决 为什么编程到 Log4j2 是安全的 API.[=28= 的不同但相关的问题]

10 Log4j2 API SLF4J 中不可用的功能

(1) Message API allows applications to log structured objects in addition to just text. Internally Log4j2 converts everything that is logged to a Message, and exposing this to the API opens up all kinds of possibilities for applications to interact with downstream logging components (filters, layouts, appenders). This can be useful if you're developing custom components as plugins to Log4j2, as well as when you're using the built-in ones. For a built-in example, see how StructuredDataMessage is used for fine-grained control over 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,除了key-value对,还有pushpop方法来支持栈功能(以前叫NDC在 Log4j 1).

(6) SLF4J 不支持 FATAL 日志级别。

(7) Log4j2 支持 custom log levels。这些可以与 log 方法一起使用,例如:logger.log(Level.getLevel("FINE"), "... msg"),或者您可以使用自定义日志级别的便捷方法生成自定义记录器包装器。

(8) Log4j2 API 接受任何对象,而不仅仅是字符串。这是允许 Log4j2 为“garbage-free”的原因之一,这意味着它将避免分配新对象。如果您的对象是数字、CharSequence 或当它实现 (Log4j2) StringBuilderFormattable 接口时,将在不创建任何临时字符串的情况下记录您的对象。

如果您记录 10 个或更少的参数,Log4j2 API 也将避免创建可变参数数组。如果您记录超过 2 个参数,SLF4J 会创建可变参数数组。

(9) 直接使用Log4j2 API即可免费获得以上内容。最重要的是,如果你真的关心避免创建临时对象(就像一些互动游戏和 low-latency 金融应用程序那样),你可以避免 auto-boxing 使用 Unbox 实用程序的原始参数 class.

(10) SLF4J 标记使用 coarse-grained 同步可能会对 multi-threaded 应用程序的性能产生影响(SLF4J-240). See the Advanced Filtering section of this performance test results 页。


免责声明:我为 Log4j2 做出贡献。