本文翻译自: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. 由于我来自JUL,我对此持偏见态度。 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的原因:
"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) (但我当然可以说这是一个懒惰的家伙)
"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. 好吧,说真的,这还不足以成为引入新依赖的理由。
"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类来实现它)。
"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?
"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在某种程度上是一个外观本身,允许交换处理程序,格式化程序甚至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的真正问题 :
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. 你可以在这里阅读它,这个修复已经成为Java 7.许多人还谈到了日志记录方法中字符串连接的开销。 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的表现与竞争对手相比并不好。
Configuration from 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. 我可以看出为什么这可能很烦人,但解决方案简短而简单。
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 我仍然会争辩
- 99.5% of the needs for output destinations are covered by what is in JUL out-of-the-box. JUL开箱即用的产品涵盖99.5%的输出目的地需求。
- 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? 那我该怎么办? 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,后端Logback: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. 上面的数字是msecs,所以越少越好。 So 10 times performance difference is by first actually pretty close. 因此,10倍的性能差异实际上非常接近。 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被重定向到null设备。
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 ms vs 0.3 ms)。 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. 与我最初的想法相反,我最终决定将SLF4J用于我的API。 This is based on a number of things and your input: 这是基于许多事情和您的意见:
It gives flexibility to choose log implementation at deployment time. 它提供了在部署时选择日志实施的灵活性。
Issues with lack of flexibility of JUL's configuration when run inside an application server. 在应用程序服务器内运行时,JUL配置缺乏灵活性的问题。
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更多。
Documentation. 文档。 The documentation for SLF4J is simply a lot more comprehensive and precise. SLF4J的文档更加全面和精确。
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! 期!
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
位于酒吧之上,而今天的JUL恰恰相反......而在过去,由于它不存在,因此它出现在零。
#1楼
参考:https://stackoom.com/question/lf2h/为什么不使用java-util-logging
#2楼
java.util.logging
was introduced in Java 1.4.java.util.logging
是在Java 1.4java.util.logging
引入的。 There were uses for logging before that, that's why many other logging APIs exist. 之前有用于记录的原因,这就是为什么存在许多其他日志记录API的原因。 Those APIs where used heavily before Java 1.4 and thus had a great marketshare that didn't just drop to 0 when 1.4 was release. 那些在Java 1.4之前大量使用的API因此具有很好的市场份额,当1.4发布时它不会降到0。JUL didn't start out all that great, many of the things you mentioned where a lot worse in 1.4 and only got better in 1.5 (and I guess in 6 as well, but I'm not too sure). JUL没有开始那么好,很多你提到的东西在1.4中差很多而且只在1.5中变得更好(我猜在6中也是如此,但我不太确定)。
JUL isn't well suited for multiple applications with different configurations in the same JVM (think multiple web applications that should not interact). JUL不适合在同一JVM中具有不同配置的多个应用程序(想想不应该交互的多个Web应用程序)。 Tomcat needs to jump through some hoops to get that working (effectively re-implementing JUL if I understood that correctly). Tomcat需要通过一些箍来实现这一点(如果我理解正确的话,有效地重新实现JUL)。
You can't always influence what logging framework your libraries use. 您无法始终影响库使用的日志记录框架。 Therefore using SLF4J (which is actually just a very thin API layer above other libraries) helps keeping a somewhat consistent picture of the entire logging world (so you can decide the underlying logging framework while still having library logging in the same system). 因此,使用SLF4J(实际上只是一个非常薄的API层,高于其他库)有助于保持整个日志世界的一致性(因此您可以决定底层日志框架,同时仍在同一系统中进行库日志记录)。
Libraries can't easily change. 图书馆不容易改变。 If a previous version of a library used to use logging-library-X it can't easily switch to logging-library-Y (for example JUL), even if the latter is clearly superious: any user of that library would need to learn the new logging framework and (at least) reconfigure their logging. 如果用于使用logging-library-X的以前版本的库它不能轻易切换到logging-library-Y(例如JUL),即使后者显然是优等的:该库的任何用户都需要学习新的日志框架和(至少)重新配置他们的日志记录。 That's a big no-no, especially when it brings no apparent gain to most people. 这是一个很大的禁忌,特别是当它给大多数人带来明显的收益时。
Having said all that I think JUL is at least a valid alternative to other logging frameworks these days. 尽管如此,我认为JUL 至少是目前其他日志框架的有效替代品。
#3楼
IMHO, the main advantage in using a logging facade like slf4j is that you let the end-user of the library choose which concrete logging implementation he wants, rather than imposing your choice to the end user. 恕我直言,使用像slf4j这样的日志外观的主要优点是你让库的最终用户选择他想要的具体日志记录实现,而不是将你的选择强加给最终用户。
Maybe he has invested time and money in Log4j or LogBack (special formatters, appenders, etc.) and prefers continuing using Log4j or LogBack, rather than configuring jul. 也许他已经在Log4j或LogBack(特殊格式化程序,appender等)上投入了时间和金钱,并且更喜欢继续使用Log4j或LogBack,而不是配置jul。 No problem: slf4j allows that. 没问题:slf4j允许这样做。 Is it a wise choice to use Log4j over jul? 使用Log4j比jul更明智吗? Maybe, maybe not. 也许,也许不是。 But you don't care. 但你不在乎。 Let the end user choose what he prefers. 让最终用户选择他喜欢的东西。
#4楼
Disclaimer : I am the founder of log4j, SLF4J and logback projects. 免责声明 :我是log4j,SLF4J和logback项目的创始人。
There are objective reasons for preferring SLF4J. 偏爱SLF4J有客观原因。 For one, SLF4J allows the end-user the liberty to choose the underlying logging framework . 首先, SLF4J允许最终用户自由选择底层日志框架 。 In addition, savvier users tend to prefer logback which offers capabilities beyond log4j , with jul falling way behind. 此外,更精明的用户往往更喜欢使用logback来提供超越log4j的功能 ,而jul则落后了。 Feature-wise jul may be sufficient for some users but for many others it just isn't. 对于某些用户而言,功能方面的jul可能就足够了,但对于许多其 In a nutshell, if logging is important to you, you would want to use SLF4J with logback as the underlying implementation. 简而言之,如果日志记录对您很重要,您可能希望将SLF4J与logback一起用作底层实现。 If logging is unimportant, jul is fine. 如果记录不重要,那么jul很好。
However, as an oss developer, you need to take into account the preferences of your users and not just your own. 但是,作为oss开发人员,您需要考虑用户的偏好而不仅仅是您自己的偏好。 It follows that you should adopt SLF4J not because you are convinced that SLF4J is better than jul but because most Java developers currently (July 2012) prefer SLF4J as their logging API. 因此你应该采用SLF4J并不是因为你确信SLF4J比jul好,而是因为大多数Java开发人员目前(2012年7月)更喜欢SLF4J作为他们的日志API。 If ultimately you decide not to care about popular opinion, consider the following facts: 如果您最终决定不关心民意,请考虑以下事实:
- those who prefer jul do so out of convenience because jul is bundled with the JDK. 那些喜欢jul的人这样做是出于方便,因为jul与JDK捆绑在一起。 To my knowledge there are no other objective arguments in favor of jul 据我所知,没有其他客观论据支持jul
- your own preference for jul is just that, a preference . 你自己对jul的偏好只是一个偏好 。
Thus, holding "hard facts" above public opinion, while seemingly brave, is a logical fallacy in this case. 因此,将“硬性事实”置于公众舆论之上,虽然看似勇敢,但在这种情况下是一种逻辑谬误。
If still not convinced, JB Nizet makes an additional and potent argument: 如果仍然不相信, JB Nizet提出了另一个有力的论点:
Except the end user could have already done this customization for his own code, or another library that uses log4j or logback. 除了最终用户可能已经为他自己的代码或使用log4j或logback的另一个库完成了这个自定义。 jul is extensible, but having to extend logback, jul, log4j and God only knows which other logging framework because he uses four libraries that use four different logging frameworks is cumbersome. jul是可扩展的,但是必须扩展logback,jul,log4j和God只知道哪个其他日志框架,因为他使用了四个使用四个不同日志框架的库是麻烦的。 By using SLF4J, you allow him to configure the logging frameworks he wants, not the one you have chosen. 通过使用SLF4J,您可以让他配置他想要的日志框架,而不是您选择的日志框架。 Remember that a typical project uses myriads of libraries, and not just yours . 请记住,一个典型的项目使用无数的库,而不仅仅是你的 。
If for whatever reason you hate the SLF4J API and using it will snuff the fun out of your work, then by all means go for jul After all, there are means to redirect jul to SLF4J . 如果无论出于何种原因你讨厌SLF4J API并使用它会扼杀你工作的乐趣,那么一定要去jul毕竟,有办法将jul重定向到SLF4J 。
By the way, jul parametrization is at least 10 times slower than SLF4J's which ends up making a noticeable difference. 顺便说一句,jul参数化比SLF4J慢至少10倍,最终产生明显的差异。
#5楼
I started, like you I suspect, using JUL because it was the easiest one to get going immediately. 我开始像我怀疑的那样,使用JUL因为它是最容易立即开始的。 Over the years, however, I have come to wish I had spent a little more time choosing. 然而,多年来,我已经希望我花了一点时间选择。
My main issue now is that we have a substantial amount of 'library' code that is used in many applications and they all use JUL. 我现在的主要问题是我们有大量的“库”代码在许多应用程序中使用,它们都使用JUL。 Whenever I use these tools in a web-service type app the logging just disappears or goes somewhere unpredictable or strange. 每当我在Web服务类型的应用程序中使用这些工具时,日志记录就会消失或变得无法预测或奇怪。
Our solution was to add a facade to the library code that meant that the library log calls did not change but were dynamically redirected to whatever logging mechanism is available. 我们的解决方案是为库代码添加一个外观,这意味着库日志调用没有改变,但是动态地重定向到可用的任何日志记录机制。 When included in a POJO tool they are directed to JUL but when deployed as a web-app they are redirected to LogBack. 当包含在POJO工具中时,它们被定向到JUL,但当部署为Web应用程序时,它们被重定向到LogBack。
Our regret - of course - is that the library code does not use parameterised logging but this can now be retrofitted as and when needed. 我们的遗憾 - 当然 - 库代码不使用参数化日志记录,但现在可以在需要时对其进行改造。
We used slf4j to build the facade. 我们使用slf4j来构建外观。
#6楼
I ran jul against slf4j-1.7.21 over logback-1.1.7, output to an SSD, Java 1.8, Win64 我通过logback-1.1.7对抗slf4j-1.7.21,输出到SSD,Java 1.8,Win64
jul ran 48449 ms, logback 27185 ms for an 1M loop. jul运行48449 ms,对于1M循环,回溯27185 ms。
Still, a little more speed and a bit nicer API is not worth 3 libraries and 800K for me. 不过,更快的速度和更好的API不值得3个库和800K对我来说。
package log;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogJUL
{
final static Logger logger = Logger.getLogger(LogJUL.class.getSimpleName());
public static void main(String[] args)
{
int N = 1024*1024;
long l = System.currentTimeMillis();
for (int i = 0; i < N; i++)
{
Long lc = System.currentTimeMillis();
Object[] o = { lc };
logger.log(Level.INFO,"Epoch time {0}", o);
}
l = System.currentTimeMillis() - l;
System.out.printf("time (ms) %d%n", l);
}
}
and 和
package log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogSLF
{
static Logger logger = LoggerFactory.getLogger(LogSLF.class);
public static void main(String[] args)
{
int N = 1024*1024;
long l = System.currentTimeMillis();
for (int i = 0; i < N; i++)
{
Long lc = System.currentTimeMillis();
logger.info("Epoch time {}", lc);
}
l = System.currentTimeMillis() - l;
System.out.printf("time (ms) %d%n", l);
}
}