<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>

          程序員必備的Java日志框架

          共 5358字,需瀏覽 11分鐘

           ·

          2021-11-27 22:15

          ??Java大聯(lián)盟

          ? 幫助萬(wàn)千Java學(xué)習(xí)者持續(xù)成長(zhǎng)

          關(guān)注



          原文:juejin.cn/post/6945753017878577165


          B 站搜索:楠哥教你學(xué)Java

          獲取更多優(yōu)質(zhì)視頻教程


          Logback 算是JAVA 里一個(gè)老牌的日志框架,從06年開(kāi)始第一個(gè)版本,迭代至今也十幾年了。不過(guò)logback最近一個(gè)穩(wěn)定版本還停留在 2017 年,好幾年都沒(méi)有更新;logback的兄弟 slf4j 最近一個(gè)穩(wěn)定版也是2017年,有點(diǎn)涼涼的意思。

          而且 logback的異步性能實(shí)在拉跨,功能簡(jiǎn)陋,配置又繁瑣,遠(yuǎn)不及Apache 的新一代日志框架 - Log4j

          目前來(lái)看,Log4j2 就是王者,其他日志框架都不是對(duì)手

          Log4j2簡(jiǎn)介

          Apache Log4j 2是 Log4j(1) 的升級(jí)版,比它的祖先 Log4j 1. x 有了很大的改進(jìn),和logback對(duì)比有很大的改進(jìn)。除了內(nèi)部設(shè)計(jì)的調(diào)整外,主要有以下幾點(diǎn)的大升級(jí):

          • 更簡(jiǎn)化的配置
          • 更強(qiáng)大的參數(shù)格式化
          • 最夸張的異步性能

          Log4j 2中,分為?API(log4j-api)和實(shí)現(xiàn)(log4j-core)?兩個(gè)模塊。API 和slf4j 是一個(gè)類型,屬于日志抽象/門面,而實(shí)現(xiàn)部分,才是Log4j 2的核心。

          • org.apache.logging.log4j ? log4j-api
          • org.apache.logging.log4j ? log4j-core

          最牛逼的性能

          最強(qiáng)的異步性能

          這個(gè)特性,算是Log4j2最強(qiáng)之處了。log4j2 在目前JAVA中的日志框架里,異步日志的性能是最高的,沒(méi)有之一。

          先來(lái)看一下,幾種日志框架benchmark對(duì)比結(jié)果(log4j2官方測(cè)試結(jié)果):

          從圖上可以看出,log4j2的異步(全異步,非混合模式)下的性能,遠(yuǎn)超log4j1和logback,簡(jiǎn)直吊打。壓力越大的情況下,吞吐上的差距就越大。在64線程測(cè)試下,log4j2的吞吐達(dá)到了180w+/s,而logback/log4j1只有不到20w,相差近十倍

          零GC(Garbage-free)

          從2.6版本開(kāi)始(2016年),log4j2 默認(rèn)就以零GC模式運(yùn)行了。什么叫零GC呢?就是不會(huì)由于log4j2而導(dǎo)致GC。

          log4j2 中各種Message對(duì)象,字符串?dāng)?shù)組,字節(jié)數(shù)組等全部復(fù)用,不重復(fù)創(chuàng)建,大大減少了無(wú)用對(duì)象的創(chuàng)建,從而做到“零GC”。

          更高性能 I/O 寫(xiě)入的支持

          log4j 還提供了一個(gè)MemoryMappedFileAppender,I/O 部分使用MemoryMappedFile來(lái)實(shí)現(xiàn),可以得到極高的I/O性能。不過(guò)在使用MemoryMappedFileAppender之前,得確定你足夠了解MemoryMappedFile的相關(guān)知識(shí),否則不要輕易使用呦。

          更強(qiáng)大的參數(shù)格式化

          API模塊和slf4j相比,提供了更豐富的參數(shù)格式化功能。

          使用{}占位符格式化參數(shù)

          在slf4j里,我們可以用{}的方式來(lái)實(shí)現(xiàn)“format”的功能(參數(shù)會(huì)直接toString替換占位符),像下面這樣:

          logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

          使用String.format的形式格式化參數(shù)

          log4j2 中除了支持{}的參數(shù)占位符,還支持String.format的形式:

          public static Logger logger = LogManager.getFormatterLogger("Foo"); logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);

          注意,如果想使用String.format的形式,需要使用LogManager.getFormatterLogger而不是LogManager.getLogger

          使用logger.printf格式化參數(shù)

          log4j2 的 Logger接口中,還有一個(gè)printf方法,無(wú)需創(chuàng)建LogManager.getFormatterLogger,就可以使用String.format的形式

          logger.printf(Level.INFO, "Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
          logger.debug("Opening connection to {}...", someDataSource);

          “惰性”打日志(lazy logging)

          這個(gè)功能雖然小,但非常實(shí)用。

          在某些業(yè)務(wù)流程里,為了留根或追溯問(wèn)題,需要完整的打印入?yún)?,一般是把入?yún)⒔o用JSON/XML序列化后用debug級(jí)別打?。?/span>

          logger.debug("入?yún)?bào)文:{}",JSON.toJSONString(policyDTO));

          如果需要追溯問(wèn)題時(shí),會(huì)將系統(tǒng)的日志級(jí)別調(diào)到debug/trace,這樣就可以打印。但是這里有個(gè)問(wèn)題,雖然在info級(jí)別下debug不會(huì)輸出內(nèi)容,但JSON.toJSONString()這個(gè)序列化的代碼一定會(huì)執(zhí)行,嚴(yán)重影響正常流程下的執(zhí)行效率。

          我們期望的結(jié)果是info級(jí)別下,連序列化都不執(zhí)行。這里可以通過(guò)isDebugEnable來(lái)判斷當(dāng)前配置下debug級(jí)別是否可以輸出:

          if(logger.isDebugEnabled()){    logger.debug("入?yún)?bào)文:{}",JSON.toJSONString(policyDTO));}

          這樣雖然可以避免不必要的序列化,但每個(gè)地方都這么寫(xiě)還是有點(diǎn)難受的,一行變成了三行。

          log4j2 的 logger 對(duì)象,提供了一系列l(wèi)ambda的支持,通過(guò)這些接口可以實(shí)現(xiàn)“惰性”打日志:

          void debug(String message, Supplier... paramSuppliers);void info(String message, Supplier... paramSuppliers);void trace(String message, Supplier... paramSuppliers);void error(String message, Supplier... paramSuppliers);
          //等同于下面的先判斷,后打印logger.debug("入?yún)?bào)文:{}",() -> JSON.toJSONString(policyDTO));
          if(logger.isDebugEnabled()){ logger.debug("入?yún)?bào)文:{}",JSON.toJSONString(policyDTO));}

          這種 Supplier + Lambda 的形式,等同于上面的先判斷 isDebugEnable 然后打印,三行的代碼變成了一行。嗯,真香。

          更簡(jiǎn)化的配置

          Log4j 2 同時(shí)支持XML/JSON/YML/Properties 四種形式的配置文件,不過(guò)最主流的還是XML的方式,最直觀。

          來(lái)看一下logback和log4j2的配置文件對(duì)比,同樣功能的配置下:

          logback.xml

          <configuration> <appender name = "File" class= "ch.qos.logback.core.rolling.RollingFileAppender">        <file>logs/app.logfile>        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">            <fileNamePattern>logs/archives/app-%d{yyyy-MM-dd}.log.gzfileNamePattern>                 <maxFileSize>1 GBmaxFileSize>        rollingPolicy>    appender>    <root level="info">      <appender-ref ref="File"/>    root>configuration>

          log4j2.xml

          <Configuration xmlns:xi="http://www.w3.org/2001/XInclude"               status="warn" name="XInclude">    <Appenders>          <RollingFile name="File" fileName="logs/app.log" filePattern="logs/archives/app-%d{yyyy-MM-dd}-%i.log.gz">              <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40c{1.} : %m%n"/>              <Policies>                  <TimeBasedTriggeringPolicy />                                    <SizeBasedTriggeringPolicy size="1 GB"/>              Policies>          RollingFile>    Appenders>    <Loggers>        <Root level="INFO">            <AppenderRef ref="File"/>        Root>    Loggers>Configuration>

          在log4j2中,appender的配置從使用 Appender 實(shí)現(xiàn)名即標(biāo)簽名的形式,語(yǔ)法上更簡(jiǎn)潔一些:

          <RollingFile name="File">  <appender name = "File" class= "ch.qos.logback.core.rolling.RollingFileAppender">

          與其他日志抽象/門面適配

          log4j2 由于拆分為 API 和 實(shí)現(xiàn)兩部分,所以可能也需要和其他日志框架進(jìn)行適配


          其他的特點(diǎn)

          • 異步隊(duì)列使用高性能隊(duì)列 - LMAX Disruptor
          • Appender豐富,有JMS/JPA/KAFKA/Http/MONGODB/CouchDB/Socket/Script等各種Appender的支持
          • 支持自定義日志級(jí)別 ……


          基本用法

          終于介紹完了Log4j2的強(qiáng)大,現(xiàn)在來(lái)介紹下Log4j2的基本使用。

          引用log4j2的maven依賴

          log4j-api在log4j-core中已經(jīng)有依賴了,直接依賴core即可

          <dependency>    <groupId>org.apache.logging.log4jgroupId>    <artifactId>log4j-coreartifactId>    <version>2.14.1version>dependency>

          注意,引用log4j2時(shí),需要注意項(xiàng)目中是否有多套日志框架共存/沖突,需要適配的問(wèn)題。細(xì)節(jié)請(qǐng)參考上面的與其他日志抽象/門面適配

          配置文件示例

          首先是配置文件,默認(rèn)的配置文件路徑為:classpath:log4j2.xml(推薦使用xml)

          <Configuration xmlns:xi="http://www.w3.org/2001/XInclude"               status="warn" name="XInclude">    <Properties>      <Property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40c{1.} : %m%n"/>    Properties>    <Appenders>                  <Console name="Console" target="SYSTEM_OUT">            <PatternLayout pattern="${PATTERN}"/>          Console>                  <RollingFile name="File" fileName="logs/app.log" filePattern="logs/archives/app-%d{yyyy-MM-dd}-%i.log.gz">              <PatternLayout pattern="${PATTERN}"/>              <Policies>                                   <TimeBasedTriggeringPolicy />                                    <SizeBasedTriggeringPolicy size="1 GB"/>              Policies>          RollingFile>    Appenders>    <Loggers>                     <Logger name="your logger/package name" level="debug" additivity="false"/>               <Root level="INFO">                                  <AppenderRef ref="Console"/>           <AppenderRef ref="File"/>        Root>    Loggers>Configuration>

          XML配置文件語(yǔ)法

          ;<Configuration>  <Properties>    <Property name="name1">valueproperty>    <Property name="name2" value="value2"/>  Properties>  <filter  ... />  <Appenders>    <appender ... >      <filter  ... />    appender>    ...  Appenders>  <Loggers>    <Logger name="name1">      <filter  ... />    Logger>    ...    <Root level="level">      <AppenderRef ref="name"/>    Root>  Loggers>Configuration>

          創(chuàng)建Logger

          直接使用log4j2的api:

          import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
          Logger logger = LogManager.getLogger(Log4j2Test.class);logger.error(...);logger.warn(...);logger.info(...);logger.debug(...);logger.trace(...);

          如果是配合slf4j使用也是可以的,只需要按照前面說(shuō)的,提前做好適配,然后使用slf4j的api即可。不過(guò)如果是新系統(tǒng)的話,建議直接上log4j2的api吧,可以享受所有l(wèi)og4j2的功能,使用slf4j之類的api時(shí),上面說(shuō)的參數(shù)格式化之類的功能就無(wú)法使用了。

          全異步配置(重要?。。?/span>

          推薦配置log4j2 全異步(all async),在你的啟動(dòng)腳本中增加一個(gè)系統(tǒng)變量的配置:

          -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector  

          總結(jié)

          Log4j2 如今性能最強(qiáng),功能最強(qiáng),而且持續(xù)更新維護(hù)。還在等什么?是時(shí)候替換你的logback/log4j1了。


          推薦閱讀

          1、Spring Boot+Vue項(xiàng)目實(shí)戰(zhàn)

          2、B站:4小時(shí)上手MyBatis Plus

          3、一文搞懂前后端分離

          4、快速上手Spring Boot+Vue前后端分離


          楠哥簡(jiǎn)介

          資深 Java 工程師,微信號(hào)?southwindss

          《Java零基礎(chǔ)實(shí)戰(zhàn)》一書(shū)作者

          騰訊課程官方 Java 面試官,今日頭條認(rèn)證大V

          GitChat認(rèn)證作者,B站認(rèn)證UP主(楠哥教你學(xué)Java)

          致力于幫助萬(wàn)千 Java 學(xué)習(xí)者持續(xù)成長(zhǎng)。




          有收獲,就點(diǎn)個(gè)在看?
          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  水蜜桃獊传媒视频 | 大香蕉伊人在线久久 | 九九九色视频 | 久久国产免费娱乐视频 | 国产一级黄色毛片 |