爲什麼不使用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. 由於我來自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的原因:

  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在某種程度上是一個外觀本身,允許交換處理程序,格式化程序甚至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. 你可以在這裏閱讀它,這個修復已經成爲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的表現與競爭對手相比並不好。

  2. 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. 我可以看出爲什麼這可能很煩人,但解決方案簡短而簡單。

  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? 那我該怎麼辦? 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: 這是基於許多事情和您的意見:

  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位於酒吧之上,而今天的JUL恰恰相反......而在過去,由於它不存在,因此它出現在零。


#1樓

參考:https://stackoom.com/question/lf2h/爲什麼不使用java-util-logging


#2樓

  1. java.util.logging was introduced in Java 1.4. java.util.logging是在Java 1.4 java.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。

  2. 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中也是如此,但我不太確定)。

  3. 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)。

  4. 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層,高於其他庫)有助於保持整個日誌世界的一致性(因此您可以決定底層日誌框架,同時仍在同一系統中進行庫日誌記錄)。

  5. 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: 如果您最終決定不關心民意,請考慮以下事實:

  1. 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
  2. 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);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章