我们已经迁移了所有代码,以使用slf4 API来使用通用API,但是现在我们正在考虑从log4j 1.x升级到log4j2.x。如果我们使用slf4j
API和log4j2作为实现,是否能够使用log4j2的所有功能?
Log4j2 API比SLF4J API丰富,并且 无法 通过SLF4J访问许多Log4j2 API功能。有关详情,请参见下文。
Log4j2实现的功能(如异步记录器,查找器,过滤器,布局和附加器)由配置控制,并且无论您在应用程序中使用的日志记录API如何都可用。
另请参阅关于 为什么可以安全地对Log4j2 API进行编程
的不同但相关的问题的此答案。 __
SLF4J中不提供的10个Log4j2 API功能
(1)Message
API
允许应用程序不仅记录文本,还记录结构化对象。在内部,Log4j2会将记录的所有内容转换为消息,并将其公开给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
样式的参数混合。{}样式具有更好的性能,可以与任何参数类型一起使用,但是该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)与SLF4J中的普通ThreadContext(MDC)相比,CloseableThreadContext提供了一些额外的便利:完成后,它会自动删除项目。例如:
// 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不支持致命日志级别。
(7)Log4j2支持自定义日志级别。这些可以与log
方法一起使用,例如:logger.log(Level.getLevel("FINE"), "... msg")
,或者您可以使用自定义日志级别的便捷方法生成自定义记录器包装。
(8)Log4j2
API接受任何对象,而不仅仅是字符串。这是使Log4j2成为“无垃圾
”的原因之一,这意味着它将避免分配新的对象。如果对象是数字,CharSequence或实现(Log4j2)StringBuilderFormattable接口,则将在不创建任何临时字符串的情况下记录您的对象。
如果您记录10个参数或更少的参数,Log4j2 API也将避免创建vararg数组。如果您记录两个以上的参数,SLF4J将创建vararg数组。
(9)仅通过直接使用Log4j2
API,即可免费获得以上内容。最重要的是,如果您真的想避免创建临时对象(如某些交互式游戏和低延迟金融应用程序那样),则可以避免使用Unbox实用程序类对原始参数进行自动装箱。
(10)SLF4J标记使用粗粒度同步可能会对多线程应用程序(SLF4J-240)产生性能影响。请参阅此性能测试结果页面的“高级筛选”部分。
免责声明:我为Log4j2做贡献。
问题内容: 我习惯在普通的log4j上使用。现在,我切换到,无法使附加程序正常工作。 下面的附加程序可以正常工作。但是永远不会创建的日志文件。为什么? 问题答案: 该标记缺少属性。
我正在考虑使用perl6和Cro来建立一个包含文本内容的网站。是否有关于将Cro与TT2等模板工具包和代码示例一起使用的最佳实践/指导供我参考?
问题内容: 我想在我的node.js脚本中使用phantomjs。有一个phantomjs- node 库。.但是不幸的是,作者使用了这个奇怪的coffee脚本代码来解释他在做什么: 现在,如果我直接将phantomjs与javascript一起使用,它将看起来像这样: 所以基本上我想用普通的javascript编写上面代码的第一段代码(通过阅读coffee脚本文档 ..这就是我所做的: 不幸的是
问题内容: 因此,我尝试按照其网站上的此(非Maven实现)和要求将slf4j添加到log4j。并尝试使用此代码 并将以下内容添加到我的库中 log4j-api-2.3.jar log4j-core-2.3.jar log4j-sl4j-impl-2.3.jar log4j-to-sl4j-2.3.jar slf4j-api-1.7.12.jar 当我尝试运行它时,出现以下错误 知道我要去哪里错了
问题内容: 我这样做: 并获得此异常: 不兼容的类型:Intf不是功能接口接口Intf中存在多个非重写的抽象方法。用-Xdiags:verbose重新编译以获得完整的输出1错误 是否有任何条件不能使用lambda替换匿名类? 问题答案: 否。没有办法“克服”这一问题。功能接口必须只有一种抽象方法。您的界面有两个: 注意:您不需要注释中提到的界面注释。但是,如果您的接口不是有效的功能接口,则可以使用
问题内容: 当需要有序集的最后一行时,通常会创建派生表并重新排序。例如,要以自动递增的方式返回表的最后3个元素: 由于也可以具有偏移量,因此如果我们事先知道此查询的行数(例如10),则可以实现相同的结果: 是否可以对表运行子查询并使用该数字动态构建一个? 问题答案: 不,不可能指定动态偏移量。 带有子查询的原始查询是执行此操作的最简单方法。