为什么不使用java.util.logging?

这是我有生以来第一次发现自己处于这样的境地:我正在编写一个开源的JavaAPI。希望被包括在许多其他项目中

对于日志记录,我(以及我的同事)一直使用JUL(java.util.logging),从来没有遇到过任何问题。然而,现在我需要更详细地了解我应该为我的API开发做些什么。我对此做了一些研究,从我得到的信息来看,我更加困惑了。因此这篇文章

因为我来自七月,所以我对此有偏见。我对其他方面的了解不多

根据我所做的研究,我得出了人们不喜欢七月的原因:

  1. ”;早在Sun发布JUL之前,我就开始用Java开发了,对我来说,继续使用logging-framework-X比学习新东西更容易。嗯,我不是开玩笑,这其实是人们说的。有了这个论点,我们都可以做COBOL了。(不过,我自己也可以肯定这是一个懒惰的家伙)

  2. ”;我不喜欢7月份记录级别的名称。好吧,说真的,这还不足以作为引入新依赖关系的理由

  3. ”;我不喜欢JUL输出的标准格式。嗯,这只是配置。您甚至不必在代码方面做任何事情。(没错,在过去,您可能必须创建自己的格式化程序类才能正确使用它)

  4. ”;我使用了其他也使用logging-framework-X的库,所以我认为使用这个库更容易。这是一个循环论证,不是吗?为什么“每个人”都使用logging-framework-X而不是JUL

  5. ”;其他人都在使用logging-framework-X”。这对我来说只是上述情况的一个特例。多数并不总是正确的

所以真正的大问题是为什么不在七月。我错过了什么?日志facades(SLF4J,JCL)存在的理由是历史上存在多个日志实现,其原因可以追溯到7月之前。如果JUL是完美的,那么伐木外墙就不存在了,或者怎么样?在某种程度上,JUL本身就是一个门面,允许处理程序、格式化程序甚至日志管理器进行交换

与其采用多种方法来做同一件事(日志记录),我们难道不应该首先质疑为什么它们是必要的吗?(看看这些原因是否仍然存在)

好的,到目前为止,我的研究已经得出了一些我可以看到的事情,可能是关于七月的真实问题:

  1. 性能。有人说SLF4J的性能优于其他产品。在我看来,这似乎是一个过早优化的案例。如果您需要每秒记录数百兆字节的日志,那么我不确定您的路径是否正确。JUL也在发展,您在Java1.4上所做的测试可能不再正确。您可以阅读相关内容这里是,此修复程序已将其转换为Java 7。许多人还讨论了日志记录方法中字符串连接的开销。然而,基于模板的日志记录避免了这一成本,而且它在7月份也存在。就我个人而言,我从来没有真正编写过基于模板的日志记录。太懒了。例如,如果我对JUL执行此操作:

    log.finest("来自用户名的查找请求="+username
    +“valueX=”valueX“+valueX
    +“价值”=“价值”+“价值”);
    

    我的IDE将警告我并请求允许它将其更改为:

    log.log(Level.FINEST),“来自username={0}、valueX={1}、valueY={2}”的查找请求;,
    新对象[]{username,valueX,valueY});
    

    。。我当然会接受的。允许!谢谢你的帮助

    所以我自己并没有写这样的语句,这是由IDE完成的

    总之,关于表现问题,我没有发现任何迹象表明,与竞争对手相比,朱尔的表现并不好

  2. 来自类路径的配置。现成的JUL无法从类路径加载配置文件。这是一个只需几行代码就可以做到这一点。我可以理解为什么这可能很烦人,但解决方法很简单

  3. 输出处理程序的可用性。JUL附带了5个现成的输出处理程序:控制台、文件流、套接字和内存。这些可以扩展,也可以编写新的。例如,这可能是写入UNIX/Linux系统日志和Windows事件日志。我个人从未有过这个要求,也没有见过它被使用过,但我肯定能解释为什么它可能是一个有用的特性。例如,Logback附带了一个Syslog的appender。但我仍然认为

    1. 99.5%的输出目的地需求由7月份开箱即用的产品满足
    2. 特殊需求可以由定制处理人员在7月上满足,而不是在其他事情上。对于我来说,没有任何东西表明为JUL编写Syslog输出处理程序比为另一个日志框架编写Syslog输出处理程序需要更多的时间

我真的很担心我忽略了什么。除了JUL之外,日志外观和日志实现的使用是如此广泛,以至于我不得不得出结论,就是我不理解。恐怕这不是第一次了。:-)

那么我应该如何处理我的API呢?我希望它能成功。我当然可以这样说;随波逐流”;并实现SLF4J(这似乎是目前最流行的),但为了我自己的利益,我仍然需要确切地了解今天的七月是什么问题,它保证了所有的模糊?我会选择七月作为我的图书馆来破坏我自己吗

测试性能

(诺兰600于2012年7月7日添加的章节)

下面是Ceki关于SLF4J参数化比JUL快10倍或更多的参考资料。所以我开始做一些简单的测试。乍一看,这种说法肯定是正确的。以下是初步结果(但请继续阅读!):

  • 执行时间SLF4J,后端回写:1515
  • 执行时间SLF4J,后端7月:12938
  • 执行时间7月:16911

上面的数字是毫秒,所以越少越好。因此,10倍的性能差异实际上非常接近。我最初的反应是:这太多了

这是测试的核心。可以看出,在循环中构造一个整数和一个字符串,然后在log语句中使用该循环:

for(int i=0;i<noOfExecutions;i++){
用于(字符x=32;x<88;x++){
String someString=Character.toString(x);
//我们在这里记录
}
}

(我希望log语句既有一个基本数据类型(在本例中为int)又有一个更复杂的数据类型(在本例中为String)。不确定这是否重要,但您已经有了它。)

SLF4J的日志语句:

logger.info(“Logging{}和{}”,i,someString);

7月的日志声明:

logger.log(Level.INFO,“Logging{0}和{1}”,新对象[]{i,someString});

JVM被“预热”,在实际测量完成之前执行一次相同的测试。Windows7上使用了Java1.7.03。使用了SLF4J(v1.6.6)和Logback(v1.0.6)的最新版本。Stdout和stderr被重定向到空设备

但是,现在要小心,事实证明JUL大部分时间都花在getSourceClassName()上,因为默认情况下,JUL会在输出中打印源类名,而Logback不会。所以我们在比较苹果和桔子。我必须再次进行测试,并以类似的方式配置日志实现,以便它们实际输出相同的内容。然而,我确实怀疑SLF4J+Logback仍将位居榜首,但与上面给出的初始数字相差甚远。请继续收看

顺便说一句:这个测试是我第一次实际使用SLF4J或Logback。愉快的经历。当你刚开始的时候,七月当然不那么受欢迎

性能测试(第2部分)

(诺兰600于2012年7月8日添加的章节)

事实证明,在7月份如何配置模式对性能并不重要,也就是说,它是否包含源名称。我尝试了一个非常简单的模式:

java.util.logging.SimpleFormatter.format="%4$s:%5$s[%1$tc]%n“;

这丝毫没有改变上述时间安排。我的探查器显示,记录器仍然花费大量时间调用getSourceClassName(),即使这不是我模式的一部分。模式不重要

因此,我在性能问题上得出的结论是,至少对于已测试的基于模板的日志语句,JUL(慢速)和SLF4J+Logback(快速)之间的实际性能差异大约有10倍。就像塞基说的

我还可以看到另一件事,即SLF4J的getLogger()调用比JUL的同上要昂贵得多。(如果我的分析器准确,则为95毫秒vs 0.3毫秒)。这是有道理的。SLF4J必须在底层日志实现的绑定上花费一些时间。这吓不倒我。在应用程序的生命周期中,这些调用应该比较少见。固定时间应在实际日志调用中

最后结论

(诺兰600于2012年7月8日添加的章节)

谢谢你的回答。与我最初的想法相反,我最终决定在API中使用SLF4J。这是基于许多事情和您的输入:

  1. 它提供了在部署时选择日志实现的灵活性

  2. 在应用服务器内部运行时,JUL的配置缺乏灵活性

  3. <li

发表评论