是否值得将slf4j与log4j2一起使用

ttp71kqs  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(187)

我不能决定是否使用slf4j与log4j2。根据在线帖子,看起来不会有任何性能影响,但它真的是必需的。
另外,以下几点也有利于log4j2:

  • SLF4J强制你的应用程序记录字符串。Log4j 2 API支持记录任何CharSequence,如果你想记录文本的话,但是也支持记录任何Object。
  • Log4j 2 API支持记录Message对象、Java 8 lambda表达式和无垃圾日志记录(它避免创建vararg数组,并避免在记录CharSequence对象时创建String)。
wtlkbnrh

wtlkbnrh1#

继续:编程到log4j 2 API而不是slf 4j

  • 安全:Log4j 2 API提供与slf 4j完全相同的保证-甚至更多。*

既然Log4j 2本身被分离成一个API和一个实现模块,那么使用SLF 4J就没有任何价值了。
是的,保持您的选项开放是一个很好的工程实践。您可能希望稍后更改为另一个日志记录实现。
在过去10年左右的时间里,在应用程序中构建这样的灵活性意味着要使用SLF 4J这样的 Package 器API。这种方法的缺点是您的应用程序不能使用底层日志库的更丰富的特性集。
Log4j 2提供了一个解决方案,它不要求您的应用程序被限制在最低的公分母。

放气阀:log4j到slf 4j

Log4j 2包含一个log4j-to-slf4j桥接模块。任何根据Log4j 2 API编码的应用程序都可以随时选择将支持实现切换到任何与slf 4j兼容的实现。

正如问题中所提到的,直接使用Log4j 2 API提供了更多的功能,并且与使用slf 4j之类的 Package 器API相比,它具有一些非功能性的优点:

  • 消息API
  • Lambda表示延迟日志记录
  • 记录任何对象,而不仅仅是字符串
  • 无垃圾:尽可能避免创建varargs或创建String
  • ClosebleThreadContext会在您使用完项目后自动将其从MDC中删除

(See 10 Log4j2 API features not available in SLF4J以获取更多详细信息。)
应用程序可以安全地使用Log4j 2 API的这些丰富功能,而不必局限于本地Log4j 2核心实现。
SLF 4J仍然是您的安全阀,但这并不意味着您的应用程序应该再针对SLF 4J API进行编码。

  • 披露:我为Log4j 2做了贡献。*

更新:似乎有一些混淆,即对Log4j 2 API编程以某种方式引入了“门面的门面”。在这方面,Log4j 2 API和SLF 4J之间没有区别。
这两个API在使用本机实现时都需要2个相关性,而在使用非本机实现时则需要4个相关性。SLF 4J和Log4j 2 API在这方面是相同的。例如:
| 必要的相依性|使用log4j-api作为API|以SLF 4J作为API|
| - -|- -|- -|
|Log4j 2作为实现|**2:**log4j-api和log4j-core|**4:**slf 4j、log4j-slf 4j-实作、log4j-应用程序界面、log4j-核心|
|作为实现回登录|**4:**log4j-api,log4j到slf 4j,slf 4j,回滚|**2:**slf 4j和回滚|

0x6upsns

0x6upsns2#

有很多考虑因素使得伐木“比乍看上去要复杂得多”,(因此几十年的激烈内讧!)

分离关注点

在一天结束的时候,代码“发送日志数据”,而这些数据“最终会到达某个地方”。但最终到达哪里取决于收集这些数据的目的。使情况变得非常复杂的是,现代软件由各种组件组成,它们都潜在地需要日志。
让我们考虑一个最坏的情况:所有组件都使用System.out#println(String)。至少所有语句都是按执行顺序的,但要辨别哪个组件生成了每一段输出可能并不简单。而且某些组件对于使用它们的上下文来说可能过于冗长。
让我们考虑下一个最差情况:所有组件都有自己的安排来控制它们的日志行为和目的地。管理员可能不得不为一个软件配置几十个日志系统。现在日志语句没有放在一起,而且它们的顺序也不对。希望它们都有一个一致的时间戳策略!
我们想要介于两者之间的产品:代码可以说“记录这个”,管理员可以控制它在哪里结束。
过于简短的历史
进入Log4J v1,它解决了“级别”、“附加器”、“过滤器”、“布局”和“上下文”等概念的问题......一个由分层的“logger命名空间”(包括一种自然利用Java包命名空间的方法)支持的概念架构,加上一个易于管理的配置机制。
这一切都很好...只要软件中的所有组件都依赖于同一个版本!曾经有一段时间,这些东西都在变化。SLF 4J的主要贡献是从组件开发人员的Angular 将这些概念“硬化”为一个稳定的API,图书馆可以依赖SLF 4J的“门面”,管理员可以选择适合他们的日志,将其组合成他们所关心的连贯记录。
(It当您的软件在容器中运行时,如果该容器有自己的日志记录需求,而您甚至不是在该容器中运行的同一个应用程序,则会更加复杂... Tomcat的JULI日志记录-用于其自己的内部日志记录-“避开”在类加载器子上下文中运行的应用程序。
Java Community Process神秘地蔑视Log4J的工作,决定在java.util.logging中实现几乎相同的概念架构,但在细节上可以说灵活性较低。然而,由于j.u.l本质上是SLF 4J语义丰富性的子集,因此很容易将SLF 4J作为j.u.l的外观。
Apache的Commons Util Logging可能不是非常必要的。Ceki自己的Logback引入了Log4J v1当时没有的管理特性--不仅是SLF 4J的一个实现,解决了所有那些非常现实的类加载器难题,而且还为管理员提供了一些吸引人的特性。

不同情况下的日志记录

但是日志记录是在很多不同的环境中完成的。在不过度阻塞线程的情况下将这些消息输出到超慢的I/O,除非需要,否则不需要付出计算日志消息的代价,在多线程环境中生成一致的日志......这些都很重要。(这就是为什么java.util.logging不常使用!)
有时候,所需的优化会影响概念架构,而概念架构又必然会影响开发人员端的API。例如,如果日志消息由于过滤而成为no-op,那么闭包所提供的机会肯定会加快速度。需要考虑使用SLF4J.next或其他API来利用该特性。API部分是SLF 4J提供的API的概念超集,因此可以很容易地将其作为SLF 4J及其下的实现的外观,或者更直接地连接到管理员所偏好的内容。
对于应用程序开发人员来说,这并不重要,只要管理员最终选择了一个日志工具,并且所有组件都可以登录到该工具。如果该工具可以通过SLF 4J * 和 * Log4J 2-the-API接受消息,那就 * 太棒了 *。Log4J 2-the-API的实现就是这样做的。您可以同时拥有蛋糕和蛋糕:您的应用程序可以享受Log4J 2-the-API提供的机会,同时仍然使用SLF 4J充分满足需求的库。如果管理员蔑视Log4J 2-the-API实现(尽管从任何Angular 都很难看出他们为什么会这样做),那么他们可以使用已经支持SLF 4J的任何东西,而不必等待该日志实现支持Log4J 2-the-API。您可以鱼与熊掌兼得。

对于 * 库开发人员 * 来说,这是一个更大的问题。安全路径是SLF 4J,因为它被广泛采用。如果日志记录对库的成功至关重要.... a.特别是如果它是多线程的,那么生成日志语句可能会很昂贵,如果它们最终不会被使用,如果有大量的日志语句需要处理,那么省略处理可能会更好。性能至关重要,而且您的用户可能会欣赏Log4J 2-the-implementation的好处,那么就执行Log4J 2。但是,您也不会因为继续使用SLF 4J而从用户那里窃取机会。如果管理员愿意,他们仍然可以使用Log4J-the-implementation。
底线是
如果你想要Log4J 2提供的特性,那就去做吧。如果你不需要,SLF 4J是一个成熟、稳定的界面,有很多支持。SLF 4J仍然是开源基础设施的重要组成部分。Ceki为社区做了很好的服务,但也有很多抱怨。
但是,由有能力的实现支持的丰富API最终会占上风。今天的稳定是明天的停滞。改进的过程会继续下去。只要它去你想去的地方,就不需要下车。

相关问题