<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          講武德,你們要的高性能日志工具 Log4j2,來了

          共 4358字,需瀏覽 9分鐘

           ·

          2020-11-25 21:15

          作者:沉默王二

          來源:SegmentFault 思否社區(qū)




          Log4j?介紹過了,SLF4J?介紹過了,Logback?也介紹過了,你以為到此終結(jié)了?


          不不不,我告訴你,還有一個 Log4j 2,顧名思義,它就是 Log4j 的升級版,就好像手機里面的 Pro 版。我作為一個寫文章方面的工具人,或者叫打工人,怎么能不寫這最后一篇。


          Log4j、SLF4J、Logback 是一個爹——Ceki Gulcu,但 Log4j 2 卻是例外,它是 Apache 基金會的產(chǎn)品。


          SLF4J 和 Logback 作為 Log4j 的替代品,在很多方面都做了必要的改進,那為什么還需要 Log4j 2 呢?我只能說 Apache 基金會的開發(fā)人員很閑,不,很拼,要不是他們這種精益求精的精神,這個編程的世界該有多枯燥,畢竟少了很多可以用“拿來就用”的輪子啊。


          上一篇也說了,老板下死命令要我把日志系統(tǒng)切換到 Logback,我順利交差了,老板很開心,夸我這個打工人很敬業(yè)。為了表達對老板的這份感謝,我決定偷偷摸摸地試水一下 Log4j 2,盡管它還不是個成品,可能會會項目帶來一定的隱患。但誰讓咱是一個敬崗愛業(yè)的打工人呢。





          01、Log4j 2 強在哪


          1)在多線程場景下,Log4j 2 的吞吐量比 Logback 高出了 10 倍,延遲降低了幾個數(shù)量級。這話聽起來像吹牛,反正是 Log4j 2 官方自己吹的。


          Log4j 2 的異步 Logger 使用的是無鎖數(shù)據(jù)結(jié)構(gòu),而 Logback 和 Log4j 的異步 Logger 使用的是 ArrayBlockingQueue。對于阻塞隊列,多線程應(yīng)用程序在嘗試使日志事件入隊時通常會遇到鎖爭用。


          下圖說明了多線程方案中無鎖數(shù)據(jù)結(jié)構(gòu)對吞吐量的影響。Log4j 2 隨著線程數(shù)量的擴展而更好地擴展:具有更多線程的應(yīng)用程序可以記錄更多的日志。其他日志記錄庫由于存在鎖競爭的關(guān)系,在記錄更多線程時,總吞吐量保持恒定或下降。這意味著使用其他日志記錄庫,每個單獨的線程將能夠減少日志記錄。



          性能方面是 Log4j 2 的最大亮點,至于其他方面的一些優(yōu)勢,比如說下面這些,可以忽略不計,文字有多短就代表它有多不重要。


          2)Log4j 2 可以減少垃圾收集器的壓力。

          3)支持 Lambda 表達式。

          4)支持自動重載配置。




          02、Log4j 2 使用示例


          廢話不多說,直接實操開干。理論知識有用,但不如上手實操一把,這也是我多年養(yǎng)成的一個“不那么良好”的編程習(xí)慣:在實操中發(fā)現(xiàn)問題,解決問題,尋找理論基礎(chǔ)。


          第一步,在 pom.xml 文件中添加 Log4j 2 的依賴:



          ????org.apache.logging.log4j
          ????log4j-api
          ????2.5


          ????org.apache.logging.log4j
          ????log4j-core
          ????2.5


          (這個 artifactId 還是 log4j,沒有體現(xiàn)出來 2,而在 version 中體現(xiàn),多少叫人誤以為是 log4j)


          第二步,來個最簡單的測試用例:


          import?org.apache.logging.log4j.LogManager;
          import?org.apache.logging.log4j.Logger;

          public?class?Demo?{
          ????private?static?final?Logger?logger?=?LogManager.getLogger(Demo.class);
          ????public?static?void?main(String[]?args)?{
          ????????logger.debug("log4j2");
          ????}
          }


          運行 Demo 類,可以在控制臺看到以下信息:


          ERROR?StatusLogger?No?log4j2?configuration?file?found.?Using?default?configuration:?logging?only?errors?to?the?console.


          Log4j 2 竟然沒有在控制臺打印“ log4j2”,還抱怨我們沒有為它指定配置文件。在這一點上,我就覺得它沒有 Logback 好,畢竟人家會輸出。


          這對于新手來說,很不友好,因為新手在遇到這種情況的時候,往往不知所措。日志里面雖然體現(xiàn)了 ERROR,但代碼并沒有編譯出錯或者運行出錯,憑什么你不輸出?


          那作為編程老鳥來說,我得告訴你,這時候最好探究一下為什么。怎么做呢?

          我們可以復(fù)制一下日志信息中的關(guān)鍵字,比如說:“No log4j2 configuration file found”,然后在 Intellij IDEA 中搜一下,如果你下載了源碼和文檔的話,不除意外,你會在 ConfigurationFactory 類中搜到這段話。


          可以在方法中打個斷點,然后 debug 一下,你就會看到下圖中的內(nèi)容。



          通過源碼,你可以看得到,Log4j 2 會去尋找 4 種類型的配置文件,后綴分別是 properties、yaml、json 和 xml。前綴是 log4j2-test 或者 log4j2。


          得到這個提示后,就可以進行第三步了。


          第三步,在 resource 目錄下增加 log4j2-test.xml 文件(方便和 Logback 做對比),內(nèi)容如下所示:


          "1.0"?encoding="UTF-8"?>

          ????
          ????????"Console"?target="SYSTEM_OUT">
          ????????????"%d{HH:mm:ss.SSS}?[%t]?%-5level?%logger{36}?-?%msg%n"/>
          ????????
          ????

          ????
          ????????"DEBUG">
          ????????????"Console"/>
          ????????
          ????



          Log4j 2 的配置文件格式和 Logback 有點相似,基本的結(jié)構(gòu)為?< Configuration>?元素,包含 0 或多個?< Appenders>?元素,其后跟 0 或多個?< Loggers>?元素,里面再跟最多只能存在一個的?< Root>?元素。


          1)配置 appender,也就是配置日志的輸出目的地。


          有 Console,典型的控制臺配置信息上面你也看到了,我來簡單解釋一下里面 pattern 的格式:


          • %d{HH:mm:ss.SSS}?表示輸出到毫秒的時間
          • %t?輸出當前線程名稱
          • %-5level?輸出日志級別,-5 表示左對齊并且固定輸出 5 個字符,如果不足在右邊補空格
          • %logger?輸出 logger 名稱,最多 36 個字符
          • %msg?日志文本
          • %n?換行

          順帶補充一下其他常用的占位符:

          • %F?輸出所在的類文件名,如 Demo.java
          • %L?輸出行號
          • %M?輸出所在方法名
          • %l?輸出語句所在的行數(shù), 包括類名、方法名、文件名、行數(shù)
          • %p?輸出日志級別
          • %c?輸出包名,如果后面跟有?{length.}?參數(shù),比如說?%c{1.},它將輸出報名的第一個字符,如?com.itwanger?的實際報名將只輸出?c.i

          再次運行 Demo 類,就可以在控制臺看到打印的日志信息了:

          10:14:04.657?[main]?DEBUG?com.itwanger.Demo?-?log4j2

          2)配置 Loggers,指定 Root 的日志級別,并且指定具體啟用哪一個 Appenders。

          3)自動重載配置。

          Logback 支持自動重載配置,Log4j 2 也支持,那想要啟用這個功能也非常簡單,只需要在 Configuration 元素上添加 monitorInterval 屬性即可。

          "30">
          ...


          注意值要設(shè)置成非零,上例中的意思是至少 30 秒后檢查配置文件中的更改。最小間隔為 5 秒。



          03、Async 示例


          除了 Console,還有 Async,可以配合文件的方式來異步寫入,典型的配置信息如下所示:


          ??
          ????"DebugFile"?fileName="debug.log">
          ??????
          ????????%d?%p?%c?[%t]?%m%n
          ??????

          ????
          ????"Async">
          ??????"DebugFile"/>
          ????
          ??

          ??
          ????"debug">
          ??????"Async"/>
          ????
          ??



          對比 Logback 的配置文件來看,Log4j 2 真的復(fù)雜了一些,不太好用,就這么直白地說吧!但自己約的,含著淚也得打完啊。把這個 Async 加入到 Appenders:


          ????
          ????????"Console"?target="SYSTEM_OUT">
          ????????????"%d{HH:mm:ss.SSS}?[%t]?%-5level?%logger{36}?-?%msg%n"/>
          ????????
          ????????"DebugFile"?fileName="debug.log">
          ????????????
          ????????????????%d?%p?%c?[%t]?%m%n
          ????????????

          ????????
          ????????"Async">
          ????????????"DebugFile"/>
          ????????
          ????

          ????
          ????????"DEBUG">
          ????????????"Console"/>
          ????????????"Async"/>
          ????????
          ????



          再次運行 Demo 類,可以在項目根路徑下看到一個 debug.log 文件,內(nèi)容如下所示:

          2020-10-30?09:35:49,705?DEBUG?com.itwanger.Demo?[main]?log4j2



          04、RollingFile 示例


          當然了,Log4j 和 Logback 我們都配置了 RollingFile,Log4j 2 也少不了。RollingFile 會根據(jù) Triggering(觸發(fā))策略和 Rollover(過渡)策略來進行日志文件滾動。如果沒有配置 Rollover,則使用 DefaultRolloverStrategy 來作為 RollingFile 的默認配置。

          觸發(fā)策略包含有,基于 cron 表達式(源于希臘語,時間的意思,用來配置定期執(zhí)行任務(wù)的時間格式)的 CronTriggeringPolicy;基于文件大小的 SizeBasedTriggeringPolicy;基于時間的 TimeBasedTriggeringPolicy。

          過渡策略包含有,默認的過渡策略 DefaultRolloverStrategy,直接寫入的 DirectWriteRolloverStrategy。一般情況下,采用默認的過渡策略即可,它已經(jīng)足夠強大。

          來看第一個基于 SizeBasedTriggeringPolicy 和 TimeBasedTriggeringPolicy 策略,以及缺省 DefaultRolloverStrategy 策略的配置示例:


          ??
          ????"RollingFile"?fileName="rolling.log"
          ?????????????????filePattern="rolling-%d{yyyy-MM-dd}-%i.log">
          ??????
          ????????%d?%p?%c{1.}?[%t]?%m%n
          ??????

          ??????
          ????????"1?KB"/>
          ??????

          ????
          ??

          ??
          ????"debug">
          ??????"RollingFile"/>
          ????
          ??



          為了驗證文件的滾動策略,我們調(diào)整一下 Demo 類,讓它多打印點日志:

          for?(int?i?=?1;i?????logger.debug("微信搜索「{}」,回復(fù)關(guān)鍵字「{}」,有驚喜哦","沉默王二",?"java");
          }

          再次運行 Demo 類,可以看到根目錄下多了 3 個日志文件:


          結(jié)合日志文件名,再來看 RollingFile 的配置,就很容易理解了。

          1)fileName 用來指定文件名。
          2)filePattern 用來指定文件名的模式,它取決于過渡策略。

          由于配置文件中沒有顯式指定過渡策略,因此 RollingFile 會啟用默認的 DefaultRolloverStrategy。

          先來看一下 DefaultRolloverStrategy 的屬性:


          再來看 filePattern 的值 rolling-%d{yyyy-MM-dd}-%i.log,其中?%d{yyyy-MM-dd}?很好理解,就是年月日;其中?%i 是什么意思呢?

          第一個日志文件名為 rolling.log(最近的日志放在這個里面),第二個文件名除去日期為 rolling-1.log,第二個文件名除去日期為 rolling-2.log,根據(jù)這些信息,你能猜到其中的規(guī)律嗎?

          其實和 DefaultRolloverStrategy 中的 max 屬性有關(guān),目前使用的默認值,也就是 7,那就當 rolling-8.log 要生成的時候,刪除 rolling-1.log。可以調(diào)整 Demo 中的日志輸出量來進行驗證。

          3)SizeBasedTriggeringPolicy,基于日志文件大小的時間策略,大小以字節(jié)為單位,后綴可以是 KB,MB 或 GB,例如 20 MB。

          再來看一個日志文件壓縮的示例,來看配置:

          "RollingFileGZ"?fileName="gz/rolling.log"
          ?????????????filePattern="gz/%d{yyyy-MM-dd-HH}-%i.rolling.gz">
          ????
          ????????%d?%p?%c{1.}?[%t]?%m%n
          ????

          ????
          ????????"1?KB"/>
          ????



          • fileName 的屬性值中包含了一個目錄 gz,也就是說日志文件都將放在這個目錄下。
          • filePattern 的屬性值中增加了一個 gz 的后綴,這就表明日志文件要進行壓縮了,還可以是 zip 格式。

          運行 Demo 后,可以在 gz 目錄下看到以下文件:


          到此為止,Log4j 2 的基本使用示例就已經(jīng)完成了。測試環(huán)境搞定,我去問一下老板,要不要在生產(chǎn)環(huán)境下使用 Log4j 2。




          04、日志手冊


          到此為止,日志系統(tǒng)的全家桶 Log4j、SLF4J、Logback、Log4j 2 都被我搞定了。也就意味著,一份將近 2 萬字的 PDF 誕生了!MD,我也要成為肝帝!
          有了這份 PDF,硬氣地告訴 Leader 或者老板吧,再也不用擔(dān)心代碼中會亂打印日志了。墻都不扶就服你。

          地址我貼一下:
          鏈接:https://pan.baidu.com/s/1dPwsQhT5OMVapE7hGi7vww?密碼:fxxy
          偷偷地告訴你吧,白嫖的感覺就是舒服,趕緊去下載吧!順帶點個贊,滿足一下我的虛榮心,畢竟這是你們賜給我的最強的寫作動力。




          點擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開更多互動和交流。

          -?END -

          瀏覽 50
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  特级片网址 | 99久久久无码国产精精品品不卡 | 天天射天天干天天日 | 影音先锋 亚洲无码 | 麻豆的视频高清在线观看完整 |