为什么不使用java.util.logging? - Why not use java.util.logging?

问题:

For the first time in my life I find myself in a position where I'm writing a Java API that will be open sourced.我有生以来第一次发现自己正在写一个将开源的Java API。 Hopefully to be included in many other projects.希望将其包含在许多其他项目中。

For logging I (and indeed the people I work with) have always used JUL (java.util.logging) and never had any issues with it.对于日志记录,我(实际上是与我一起工作的人)一直使用JUL(java.util.logging),并且从未遇到过任何问题。 However now I need to understand in more detail what I should do for my API development.但是,现在我需要更详细地了解我应该为API开发做什么。 I've done some research on this and with the information I've got I just get more confused.我对此进行了一些研究,并根据所获得的信息感到更加困惑。 Hence this post.因此,这个职位。

Since I come from JUL I'm biased on that.由于我来自七月,所以我对此有偏见。 My knowledge of the rest is not that big.我对其余的知识并不多。

From the research I've done I've come up with these reasons why people do not like JUL:从我所做的研究中,我得出了人们不喜欢JUL的这些原因:

  1. "I started developing in Java long before Sun released JUL and it was just easier for me to continue with logging-framework-X rather than to learn something new" . “我很早在Sun发布JUL之前就开始用Java进行开发,对于我而言,继续使用logging-framework-X而不是学习新知识只是一件容易的事。” Hmm.唔。 I'm not kidding, this is actually what people say.我不是在开玩笑,这实际上是人们所说的。 With this argument we could all be doing COBOL.有了这个论点,我们所有人都可能在做COBOL。 (however I can certainly relate to this being a lazy dude myself) (不过我当然可以认为自己是个懒惰的家伙)

  2. "I don't like the names of the logging levels in JUL" . “我不喜欢JUL中的日志记录级别的名称” Ok, seriously, this is just not enough of a reason to introduce a new dependency.好的,很严重,这还不足以引入新的依赖关系。

  3. "I don't like the standard format of the output from JUL" . “我不喜欢JUL输出的标准格式” Hmm.唔。 This is just configuration.这只是配置。 You do not even have to do anything code-wise.您甚至不必执行任何代码明智的事情。 (true, back in old days you may have had to create your own Formatter class to get it right). (是的,在过去,您可能必须创建自己的Formatter类才能正确使用它)。

  4. "I use other libraries that also use logging-framework-X so I thought it easier just to use that one" . “我使用了其他也使用logging-framework-X的库,因此我认为仅使用该库就更容易了” This is a circular argument, isn't ?这是一个循环的论证,不是吗? Why does 'everybody' use logging-framework-X and not JUL?为什么“每个人”都使用logging-framework-X而不使用JUL?

  5. "Everybody else is using logging-framework-X" . “其他人都在使用logging-framework-X” This to me is just a special case of the above.对我来说,这只是上述情况的特例。 Majority is not always right.多数并不总是正确的。

So the real big question is why not JUL?因此,真正的大问题是为什么不选择JUL? . What is it I have missed ?我错过了什么? The raison d'être for logging facades (SLF4J, JCL) is that multiple logging implementations have existed historically and the reason for that really goes back to the era before JUL as I see it.记录正面(SLF4J,JCL)的理由是,历史上已经存在多种记录实现,其原因确实可以追溯到我看到的JUL之前的时代。 If JUL was perfect then logging facades wouldn't exist, or what?如果JUL是完美的,那么将不存在伐木外观,还是什么? To make matters more confusing JUL is to some extent a facade itself, allowing Handlers, Formatters and even the LogManager to be swapped.让事情变得更加混乱的是,JUL在某种程度上是一种外观,它允许交换Handlers,Formatters甚至LogManager。

Rather than embracing multiple ways of doing the same thing (logging), shouldn't we question why they were necessary in the first place?而不是采用多种方法来做同一件事(记录),我们是否应该首先质疑为什么必须这样做? (and see if those reasons still exist) (并查看这些原因是否仍然存在)

Ok, my research so far has led to a couple of things that I can see may be real issues with JUL:好的,到目前为止,我的研究已经发现了几件可能是JUL真正问题的事情:

  1. Performance .表现 Some say that performance in SLF4J is superior to the rest.有人说SLF4J的性能优于其他产品。 This seems to me to be a case of premature optimization.在我看来,这似乎是过早优化的一种情况。 If you need to log hundreds of megabytes per second then I'm not sure you are on the right path anyway.如果您需要每秒记录数百兆字节,那么我不确定您是否走在正确的道路上。 JUL has also evolved and the tests you did on Java 1.4 may no longer be true. JUL也已经发展,您在Java 1.4上进行的测试可能不再正确。 You can read about it here and this fix has made it into Java 7. Many also talk about the overhead of string concatenation in logging methods.您可以在此处阅读有关此内容的信息,此修复程序已将其纳入Java7。许多人还谈到了日志记录方法中字符串连接的开销。 However template based logging avoids this cost and it exist also in JUL.但是,基于模板的日志记录避免了这种开销,并且它在JUL中也存在。 Personally I never really write template based logging.我个人从来没有真正写过基于模板的日志记录。 Too lazy for that.太懒了。 For example if I do this with JUL:例如,如果我使用JUL进行此操作:

    log.finest("Lookup request from username=" + username + ", valueX=" + valueX + ", valueY=" + valueY));

    my IDE will warn me and ask permission that it should change it to:我的IDE会警告我,并请求允许将其更改为:

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", new Object[]{username, valueX, valueY});

    .. which I will of course accept. ..我当然会接受。 Permission granted !许可授予 ! Thank you for your help.感谢您的帮助。

    So I don't actually write such statements myself, that is done by the IDE.因此,我实际上并不亲自编写此类语句,而是由IDE完成的。

    In conclusion on the issue of performance I haven't found anything that would suggest that JUL's performance is not ok compared to the competition.总之,在性能问题上,我没有发现任何暗示JUL的性能与竞争对手相比不佳的信息。

  2. Configuration from classpath .从classpath配置 Out-of-the-box JUL cannot load a configuration file from the classpath.开箱即用的JUL无法从类路径加载配置文件。 It is a few lines of code to make it do so.这样做需要几行代码 I can see why this may be annoying but the solution is short and simple.我可以理解为什么这可能很烦人,但是解决方案又短又简单。

  3. Availability of output handlers .输出处理程序的可用性 JUL comes with 5 output handlers out-of-the-box: console, file stream, socket and memory. JUL带有5个开箱即用的输出处理程序:控制台,文件流,套接字和内存。 These can be extended or new ones can be written.这些可以扩展,也可以编写新的。 This may for example be writing to UNIX/Linux Syslog and Windows Event Log.例如,这可能正在写入UNIX / Linux Syslog和Windows事件日志。 I have personally never had this requirement nor have I seen it used but I can certainly relate to why it may be a useful feature.我个人从来没有这个要求,也没有看到它使用过,但是我可以肯定地解释为什么它可能是一个有用的功能。 Logback comes with an appender for Syslog for example.例如,Logback附带了Syslog的附加程序。 Still I would argue that我仍然会争辩说

    1. 99.5% of the needs for output destinations are covered by what is in JUL out-of-the-box.开箱即用的JUL可以满足99.5%的输出目的地需求。
    2. Special needs could be catered for by custom handlers on top of JUL rather than on top of something else.定制处理程序可以在JUL之上而不是其他之上满足特殊需求。 There's nothing to me that suggests that it takes more time to write a Syslog output handler for JUL than it does for another logging framework.在我看来,没有什么比为其他日志记录框架花费更多的时间来为JUL编写Syslog输出处理程序了。

I'm really concerned that there's something I've overlooked.我真的很担心我忽略了某些事情。 The use of logging facades and logging implementations other than JUL is so widespread that I have to come to the conclusion that it's me who just doesn't understand.除了JUL之外,对日志外观和日志实现的使用是如此广泛,以至于我不得不得出结论,就是我自己不了解。 That wouldn't be the first time, I'm afraid.恐怕这不是第一次。 :-) :-)

So what should I do with my API?那么我应该如何处理我的API? I want it to become successful.我希望它能够成功。 I can of course just "go with the flow" and implement SLF4J (which seems the most popular these days) but for my own sake I still need to understand exactly what is wrong with the JUL of today that warrants all the fuzz?我当然可以“顺其自然”并实现SLF4J(这是当今最流行的),但是出于我自己的考虑,我仍然需要确切地了解今天的JUL到底有什么毛病? Will I sabotage myself by choosing JUL for my library ?我会为我的图书馆选择JUL来破坏自己吗?

Testing performance测试性能

(section added by nolan600 on 07-JUL-2012) (部分由nolan600在2012年7月7日添加)

There's a reference below from Ceki about SLF4J's parametrization being 10 times or more faster than JUL's.以下来自Ceki的参考资料表明SLF4J的参数化速度比JUL的速度快10倍或更多。 So I've started doing some simple tests.所以我已经开始做一些简单的测试。 At first glance the claim is certainly correct.乍一看,这一主张当然是正确的。 Here are the preliminary results (but read on!):这是初步结果(但请继续阅读!):

  • Execution time SLF4J, backend Logback: 1515执行时间SLF4J,后端登录:1515
  • Execution time SLF4J, backend JUL: 12938执行时间SLF4J,后端JUL:12938
  • Execution time JUL: 16911执行时间JUL:16911

The numbers above are msecs so less is better.上面的数字是毫秒,所以越少越好。 So 10 times performance difference is by first actually pretty close.所以实际上十倍的性能差异实际上是非常接近的。 My initial reaction: That is a lot !我最初的反应:很多!

Here is the core of the test.这是测试的核心。 As can be seen an integer and a string is construted in a loop which is then used in the log statement:可以看出,整数和字符串在循环中构造,然后在log语句中使用该循环:

    for (int i = 0; i < noOfExecutions; i++) {
        for (char x=32; x<88; x++) {
            String someString = Character.toString(x);
            // here we log 
        }
    }

(I wanted the log statement to have both a primitive data type (in this case an int) and a more complex data type (in this case a String). Not sure it matters but there you have it.) (我希望log语句同时具有原始数据类型(在这种情况下为int)和更复杂的数据类型(在这种情况下为String)。不确定是否重要,但是有。)

The log statement for SLF4J: SLF4J的日志语句:

logger.info("Logging {} and {} ", i, someString);

The log statement for JUL: JUL的日志语句:

logger.log(Level.INFO, "Logging {0} and {1}", new Object[]{i, someString});

The JVM was 'warmed up' with the same test executed once before the actual measurement was done.在完成实际测量之前,对JVM进行了“热身”,并执行了一次相同的测试。 Java 1.7.03 was used on Windows 7. Latest versions of SLF4J (v1.6.6) and Logback (v1.0.6) was used. Windows 7使用Java 1.7.03。使用了最新版本的SLF4J(v1.6.6)和Logback(v1.0.6)。 Stdout and stderr was redirected to null device. Stdout和stderr被重定向到空设备。

However, careful now, it turns out JUL is spending most of its time in getSourceClassName() because JUL by default prints the source class name in the output, while Logback doesn't.但是,现在要小心,事实证明JUL大部分时间都花在getSourceClassName()因为默认情况下,JUL在输出中输出源类名称,而Logback则不输出。 So we are comparing apples and oranges.因此,我们正在比较苹果和橙子。 I have to do the test again and configure the logging implementations in a similar manner so that they actually output the same stuff.我必须再次进行测试,并以类似的方式配置日志记录实现,以便它们实际上输出相同的内容。 I do however suspect that SLF4J+Logback will still come out on top but far from the initial numbers as given above.但是,我确实怀疑SLF4J + Logback仍将排在首位,但与上面给出的初始数字相去甚远。 Stay tuned.敬请关注。

Btw: The test was first time I've actually worked with SLF4J or Logback.顺便说一句:该测试是我第一次真正使用SLF4J或Logback。 A pleasant experience.令人愉快的经历。 JUL is certainly a lot less welcoming when you are starting out.刚开始时,JUL当然不受欢迎。

Testing performance (part 2)测试性能(第2部分)

(section added by nolan600 on 08-JUL-2012) (部分由nolan600在2012年7月8日添加)

As it turns out it doesn't really matter for performance how you configure your pattern in JUL, ie whether or not it includes the source name or not.事实证明,在JUL中如何配置模式(即,是否包含源名称)对于性能而言并不重要。 I tried with a very simple pattern:我尝试了一个非常简单的模式:

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

and that did not change the above timings at all.而这完全没有改变上述时间。 My profiler revealed that the logger still spent a lot of time in calls to getSourceClassName() even if this was not part of my pattern.我的探查器显示,即使这不是我的模式的一部分,记录器仍然花费大量时间来调用getSourceClassName() The pattern doesn't matter.模式无关紧要。

I'm therefore concluding on the issue of performance that at least for the tested template based log statement there seems to be roughly a factor of 10 in real performance difference between JUL (slow) and SLF4J+Logback (quick).因此,我在性能问题上得出结论,至少对于经过测试的基于模板的日志语句,JUL(慢)和SLF4J + Logback(快速)之间的实际性能差异似乎大约是10倍。 Just like Ceki said.就像切基说的那样。

I can also see another thing namely that SLF4J's getLogger() call is a lot more expensive than JUL's ditto.我还可以看到另一件事,那就是SLF4J的getLogger()调用比JUL的同上更加昂贵。 (95 ms vs 0.3 ms if my profiler is accurate). (95毫秒vs. 0.3毫秒(如果我的探查器准确的话))。 This makes sense.这是有道理的。 SLF4J has to do some time on the binding of the underlying logging implementation. SLF4J必须在底层日志记录实现的绑定上花费一些时间。 This doesn't scare me.这不会吓到我。 These calls should be somewhat rare in the lifetime of an application.在应用程序的生命周期中,这些调用应该很少见。 The fastness should be in the actual log calls.牢度应在实际的日志调用中。

Final conclusion定论

(section added by nolan600 on 08-JUL-2012) (部分由nolan600在2012年7月8日添加)

Thank you for all your answers.感谢您的所有答复。 Contrary to what I initially thought I've ended up deciding to use SLF4J for my API.与我最初的想法相反,我最终决定对我的API使用SLF4J。 This is based on a number of things and your input:这基于许多因素和您的输入:

  1. It gives flexibility to choose log implementation at deployment time.它提供了在部署时选择日志实现的灵活性。

  2. Issues with lack of flexibility of JUL's configuration when run inside an application server.在应用服务器中运行时,JUL的配置缺乏灵活性的问题。

  3. SLF4J is certainly a lot faster as detailed above in particular if you couple it with Logback. SLF4J肯定比上面详述的要快得多,特别是如果将其与Logback结合使用。 Even if this was just a rough test I have reason to believe that a lot more effort has gone into optimization on SLF4J+Logback than on JUL.即使这只是一个粗略的测试,我也有理由相信,在SLF4J + Logback上进行的优化比在JUL上进行了更多的努力。

  4. Documentation.文档。 The documentation for SLF4J is simply a lot more comprehensive and precise. SLF4J的文档更加全面和精确。

  5. Pattern flexibility.模式灵活性。 As I did the tests I set out to have JUL mimic the default pattern from Logback.在进行测试时,我开始让JUL模仿Logback的默认模式。 This pattern includes the name of the thread.此模式包括线程的名称。 It turns out JUL cannot do this out of the box.事实证明,JUL无法开箱即用。 Ok, I haven't missed it until now, but I don't think it is a thing that should be missing from a log framework.好的,直到现在我都没有错过它,但是我认为日志框架不应该缺少它。 Period!时期!

  6. Most (or many) Java projects today use Maven so adding a dependency is not that big a thing especially if that dependency is rather stable, ie doesn't constantly change its API.如今,大多数(或许多)Java项目都使用Maven,因此添加依赖项并不是一件大事,尤其是如果该依赖项相当稳定(即不会不断更改其API)的话。 This seems to be true for SLF4J.对于SLF4J似乎确实如此。 Also the SLF4J jar and friends are small in size. SLF4J罐子和朋友的尺寸也很小。

So the strange thing that happened was that I actually got quite upset with JUL after having worked a bit with SLF4J.所以发生的一件奇怪的事情是,我在与SLF4J一起工作之后实际上对JUL感到不高兴。 I still regret that it has to be this way with JUL.我仍然感到遗憾的是,JUL必须采取这种方式。 JUL is far from perfect but kind of does the job. JUL远非完美,但可以胜任。 Just not quite well enough.只是不够好。 The same can be said about Properties as an example but we do not think about abstracting that so people can plug in their own configuration library and what have you.Properties为例也可以这样说,但是我们不考虑抽象化,因此人们可以插入自己的配置库以及您所拥有的。 I think the reason is that Properties comes in just above the bar while the opposite is true for JUL of today ... and in the past it came in at zero because it didn't exist.我认为原因是, Properties在排行榜的正上方,而对于今天的7月,情况恰恰相反……过去,由于不存在,所以排在零位。


解决方案:

参考一: https://stackoom.com/question/lf2h
参考二: Why not use java.util.logging?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章