<?xml version="1.0" encoding="UTF-8"?>
<!--日志級(jí)別以及優(yōu)先級(jí)排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,這個(gè)用于設(shè)置log4j2自身內(nèi)部的信息輸出,可以不設(shè)置,當(dāng)設(shè)置成trace時(shí),你會(huì)看到log4j2內(nèi)部各種詳細(xì)輸出-->
<!--monitorInterval:Log4j能夠自動(dòng)檢測(cè)修改配置 文件和重新配置本身,可設(shè)置一個(gè)非零的間隔秒數(shù)來(lái)檢測(cè)配置變更 -->
<Configuration status="WARN" monitorInterval="60">
<!-- 自定義一些變量 -->
<Properties>
<!-- 變量定義 -->
<Property name="log_base_dir">/app_data/logs/my_app</Property>
<!-- Appender在將日志數(shù)據(jù)寫(xiě)入目標(biāo)位置之前,一般會(huì)將日志數(shù)據(jù)通過(guò)Layout進(jìn)行格式化。PatternLayout可以使用與C語(yǔ)言printf函數(shù)類(lèi)似
的轉(zhuǎn)換模式來(lái)指定輸出格式。常見(jiàn)的配置如下:
- %d{yyyy-MM-dd HH:mm:ss.SSS} : 日志生成時(shí)間,輸出格式為“年-月-日 時(shí):分:秒.毫秒”
- %p : 日志輸出格式
- %c : logger的名稱(chēng)
- %m : 日志內(nèi)容,即 logger.info("message")
- %n : 換行符
- %T : 線(xiàn)程號(hào)
- %L : 日志輸出所在行數(shù)
- %M : 日志輸出所在方法名 -->
<Property name="log_pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5p][%T][%c.%M:%L] %msg%xEx%n</Property>
<!-- 單個(gè)日志文件最大大小,單位可以是KB, MB or GB -->
<Property name="max_single_file_size">1MB</Property>
</Properties>
<!-- 使用Appenders元素可以將日志事件數(shù)據(jù)寫(xiě)到各種目標(biāo)位置(目前可以為控制臺(tái)、文件、多種數(shù)據(jù)庫(kù)API、遠(yuǎn)程套接字服務(wù)器、Apache Flume、
JMS、遠(yuǎn)程UNIX Syslog daemon),其內(nèi)的每個(gè)Appender都必須要有一個(gè)name屬性作為唯一標(biāo)識(shí),該標(biāo)識(shí)的值在Logger中通過(guò)AppenderRef來(lái)引
用,從而將該Appender配置到該Logger中 -->
<Appenders>
<!-- Console Appender常用于將日志輸出到System.out,一般用在開(kāi)發(fā)環(huán)境 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 只接受程序中DEBUG級(jí)別的日志進(jìn)行處理-->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 在大多數(shù)情況下,Appender將格式化LogEvent的責(zé)任委托給Layout -->
<PatternLayout pattern="${log_pattern}"/>
</Console>
<!-- RollingFile Appender會(huì)將日志輸出到fileName屬性指定的文件中,且需要指定TriggeringPolicy和RolloverStrategy。其中
TriggeringPolicy決定是否生成新的日志文件,RolloverStrategy決定如何生成新的日志文件。如果沒(méi)有配置RolloverStrategy,則會(huì)
使用DefaultRolloverStrategy。從2.5開(kāi)始,可以在DefaultRolloverStrategy中配置一個(gè)自定義的刪除動(dòng)作。從2.8開(kāi)始,如果沒(méi)有指定
文件名,則會(huì)使用DirectWriteRolloverStrategy來(lái)代替DefaultRolloverStrategy -->
<!-- 這個(gè)RollingFile Appender會(huì)打印出所有的DEBUG及以下級(jí)別(DEBUG、INFO、ERROR、FATAL、OFF)的信息 -->
<RollingFile name="DebugLogRollingFile" fileName="${log_base_dir}/my_app_debug.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_debug_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}" charset="UTF-8"/>
<!-- Policies表示一個(gè)CompositeTriggeringPolicy,可以組合多個(gè)TriggeringPolicy,只要內(nèi)部的任意一個(gè)TriggeringPolicy
滿(mǎn)足觸發(fā)條件,都會(huì)滾動(dòng)日志 -->
<Policies>
<!-- TimeBasedTriggeringPolicy用于按時(shí)間滾動(dòng)日志。只要filePattern屬性值中的日期/時(shí)間模式(pattern)不再應(yīng)用于當(dāng)
前文件時(shí)就進(jìn)行日志滾動(dòng)。這種規(guī)則通過(guò)interval和modulate屬性來(lái)配置。interval屬性指定一個(gè)整數(shù),用于基于日期/時(shí)間模式中
的最小的時(shí)間單位數(shù)滾動(dòng)一次。例如,filePattern值為/app_data/logs/my_app/$${date:yyyy_MM_dd}/my_app_%d{yyyy_
MM_dd_HH}_%i.log,這里使用小時(shí)作為最小的時(shí)間單位時(shí),假如interval參數(shù)值為4,則表示每4小時(shí)滾動(dòng)一次。默認(rèn)值為1。
modulate表示是否調(diào)整interval屬性值以便下次滾動(dòng)發(fā)生在interval邊界處。如果時(shí)間最小單位為小時(shí),當(dāng)前時(shí)間為早上3點(diǎn),間隔
為4小時(shí),則第一次滾動(dòng)將發(fā)生在早上4點(diǎn)時(shí)(而不是早上7點(diǎn)),后續(xù)滾動(dòng)將發(fā)生在早上8點(diǎn)、中午12點(diǎn)、下午4點(diǎn)等時(shí)刻 -->
<TimeBasedTriggeringPolicy interval="1" modulate="false"/>
<!-- SizeBasedTriggeringPolicy用于按文件大小滾動(dòng)日志。每當(dāng)日志文件超過(guò)size指定的大小(一般不超過(guò)幾十MB,否則使用軟
件打開(kāi)導(dǎo)出的日志時(shí)很不方便),則這size大小的日志會(huì)自動(dòng)存入按filePattern屬性指定建立的文件夾下面并進(jìn)行壓縮存檔 -->
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<!-- DefaultRolloverStrategy可以同時(shí)接受RollingFileAppender中filePattern屬性值中日期/時(shí)間和整數(shù)計(jì)數(shù)器(%i)的
pattern,當(dāng)日期/時(shí)間滿(mǎn)足條件時(shí),則會(huì)使用當(dāng)前的日期/時(shí)間生成新的日志文件,如果filePattern屬性值中含有一個(gè)整數(shù)計(jì)數(shù)器%i,則
在每次滾動(dòng)時(shí)該整數(shù)都會(huì)增加,如果filePattern屬性值中同時(shí)包含了日期/時(shí)間和整數(shù)計(jì)數(shù)器(%i),計(jì)數(shù)器會(huì)在日期/時(shí)間不變時(shí)而滿(mǎn)足
其他滾動(dòng)觸發(fā)條件時(shí)(文件大小)開(kāi)始自增,直到日期/時(shí)間發(fā)生變化時(shí),計(jì)數(shù)器會(huì)重新自增。以.gz、.zip、.bz2、deflate、pack200
或xz結(jié)尾的filePattern值,會(huì)在日志文件歸檔時(shí)以后綴對(duì)應(yīng)的格式進(jìn)行壓縮。min屬性指定計(jì)數(shù)器的最小值,默認(rèn)為1。max屬性指定計(jì)數(shù)
器的最大值,一旦計(jì)數(shù)器達(dá)到了最大值,最早的歸檔將會(huì)在每次滾動(dòng)時(shí)被刪除,默認(rèn)值為7。fileIndex屬性如果設(shè)置為max(默認(rèn)),則具
有更大索引的文件比具有更小索引的文件內(nèi)容更新,如果設(shè)置為min,文件將重命名且計(jì)數(shù)器將遵循Fixed Window策略,這兩種情況均有可
能導(dǎo)致批量的文件重命名,自2.8版本開(kāi)始,如果fileIndex屬性設(shè)置為nomax,則min和max屬性值都將會(huì)被忽略,文件編號(hào)將每次遞增1,
每次滾動(dòng)都會(huì)遞增到更大的值,且沒(méi)有最大文件編號(hào)的限制 -->
<!--<DefaultRolloverStrategy max="100" min="1" fileIndex = "nomax"/>-->
<DefaultRolloverStrategy fileIndex="nomax">
<!-- Log4j 2.5引入了刪除動(dòng)作(Delete元素)。在滾動(dòng)刪除舊的日志文件時(shí),相比使用DefaultRolloverStrategy的max屬
性,該功能可以讓用戶(hù)擁有更多的刪除控制。刪除動(dòng)作可以讓用戶(hù)配置若干個(gè)條件來(lái)刪除相對(duì)于基準(zhǔn)目錄的文件。該功能可以刪除非日
志文件,使用時(shí)一定要小心??梢酝ㄟ^(guò)testMode屬性來(lái)測(cè)試配置是否會(huì)錯(cuò)刪文件。basePath屬性值用于指定刪除文件的基準(zhǔn)目錄,必
須顯式指定。maxDepth屬性指定掃描目錄的最大層級(jí),0表示僅能訪(fǎng)問(wèn)基準(zhǔn)目錄(安全限制不能訪(fǎng)問(wèn)的情況除外),
Integer.MAX_VALUE值表示可以訪(fǎng)問(wèn)所有層級(jí)。默認(rèn)值為1,表示僅掃描基準(zhǔn)目錄下的文件。testMode屬性值如果設(shè)置為true,文件
不會(huì)實(shí)際刪除,而是在status logger打印一條INFO級(jí)別的消息,可以使用該功能來(lái)測(cè)試是否會(huì)錯(cuò)刪目標(biāo)文件,默認(rèn)為false。-->
<!-- 這里的Delete元素配置了每次滾動(dòng)都會(huì)刪除基準(zhǔn)目錄下匹配“*/my_app_debug_*.log.gz”日志文件,只要9分鐘以前的日志文
件總大小超過(guò)2MB,或9分鐘以前的日志文件文件總數(shù)超過(guò)2個(gè)就按時(shí)間順序刪除較早的日志文件。該元素可以防止日志文件所在分區(qū)的
磁盤(pán)空間被占滿(mǎn)。特別需要注意的是,只有在發(fā)生日志滾動(dòng)時(shí)才會(huì)嘗試進(jìn)行刪除,否則即使?jié)M足了刪除條件,但如果沒(méi)有新的滾動(dòng)日志
生成的話(huà)也不會(huì)發(fā)生刪除操作。 -->
<Delete basePath="${log_base_dir}" maxDepth="2">
<!-- Delete元素里可以指定若干個(gè)PathCondition類(lèi)型的元素。如果指定了不止一個(gè)條件,則這些條件都需要在刪除之前接受
某個(gè)路徑。這些條件可以嵌套,只有外部條件接受某個(gè)路徑之后,其內(nèi)部條件才會(huì)決定是否接受該路徑。如果這些條件沒(méi)有嵌套,
則它們的執(zhí)行順序是任意的。這些條件也可以通過(guò)使用IfAll, IfAny和IfNot等組合條件進(jìn)行AND、OR和NOT等邏輯運(yùn)算。用戶(hù)
也可以創(chuàng)建自定義條件或使用內(nèi)置條件:
- IfFileName:接受匹配正則表達(dá)式或glob的文件路徑;
- IfLastModified:接受比指定時(shí)段早或一樣早的文件;
- IfAccumulatedFileCount:在遍歷文件樹(shù)時(shí)文件總數(shù)超過(guò)文件數(shù)上限后接受路徑;
- IfAccumulatedFileSize:在遍歷文件樹(shù)時(shí)文件總大小超過(guò)上限后接受路徑;
- IfAll:如果所有內(nèi)嵌條件都接受了某個(gè)路徑才會(huì)接受該路徑,相當(dāng)于AND邏輯,其內(nèi)嵌條件的執(zhí)行順序是任意的;
- IfAny:如果任意一個(gè)內(nèi)嵌條件接受了某個(gè)目錄就接受該目錄,相當(dāng)于OR邏輯,其內(nèi)嵌條件的執(zhí)行順序是任意的;
- IfNot:如果內(nèi)嵌條件不接受某個(gè)路徑就接收該路徑,相當(dāng)于NOT邏輯。-->
<!-- IfFileName可以通過(guò)glob(使用受限的模式語(yǔ)言,比正則更簡(jiǎn)單)或regex屬性(正則)來(lái)匹配相對(duì)路徑(相對(duì)于Delete
的basePath屬性指定的基準(zhǔn)目錄)-->
<!-- 當(dāng)外部的條件滿(mǎn)足時(shí)才會(huì)計(jì)算內(nèi)部的條件,內(nèi)部的同級(jí)條件的計(jì)算順序是任意的。 -->
<IfFileName glob="*/my_app_debug_*.log.gz">
<!-- IfLastModified可以通過(guò)age屬性值來(lái)指定接受最后修改時(shí)間為指定時(shí)間或早于指定時(shí)間的路徑,該屬性的值可參考
org.apache.logging.log4j.core.appender.rolling.action.Duration.parse(CharSequence text)方法的文檔 -->
<!-- 這里的IfLastModified指定刪除達(dá)到或超過(guò)60天內(nèi)的文件 -->
<IfLastModified age="9m">
<!-- 這里的IfAny內(nèi)嵌了兩個(gè)PathCondition,表示滿(mǎn)足任意一個(gè)條件即可 -->
<IfAny>
<!-- IfAccumulatedFileSize可通過(guò)exceeds屬性值指定一個(gè)文件總大小上限值。如果文件數(shù)超過(guò)了該上限值
則刪除文件 -->
<IfAccumulatedFileSize exceeds="2MB"/>
<!-- IfAccumulatedFileCount可通過(guò)exceeds屬性值指定一個(gè)文件總數(shù)上限值。如果文件數(shù)超過(guò)了該上限值
則刪除文件 -->
<IfAccumulatedFileCount exceeds="2"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="InfoLogRollingFile" fileName="${log_base_dir}/my_app_info.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_info_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_info_*.log.gz">
<!-- 這里表示匹配“*/my_app_info_*.log.gz”模式的日志文件的刪除策略如下:
- 只要日志文件總數(shù)量超過(guò)5個(gè)就刪除按時(shí)間順序最早的日志文件
- 只要日志文件總大小超過(guò)10MB就會(huì)刪除按時(shí)間順序最早的日志文件
- 只要日志文件最近修改時(shí)間為9分鐘前或更早就會(huì)刪除按時(shí)間順序最早的日志文件 -->
<IfAny>
<IfAccumulatedFileSize exceeds="8MB"/>
<IfAccumulatedFileCount exceeds="5"/>
<IfLastModified age="9m"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="WarnLogRollingFile" fileName="${log_base_dir}/my_app_warn.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_warn_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_warn_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="ErrorLogRollingFile" fileName="${log_base_dir}/my_app_error.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_error_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_error_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<!-- 記錄druid的SQL語(yǔ)句 -->
<RollingFile name="DruidSqlRollingFile" fileName="${log_base_dir}/druid.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/druid_%d{yyyy_MM_dd_HH}_%i.log.gz">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2" testMode="true">
<IfFileName glob="*/druid_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<!--定義logger,只有定義了logger并引入的appender,appender才會(huì)生效-->
<Loggers>
<!-- 當(dāng)Logger在配置文件中聲明時(shí),就創(chuàng)建了一個(gè)LoggerConfig對(duì)象,兩者一一對(duì)應(yīng),LoggerConfig包含一些Filter、這些
Filters用于過(guò)濾傳遞給任意Appender的LogEvent,它還包含一些Appender的引用。Logger本身執(zhí)行無(wú)指向的動(dòng)作,它僅含有一
個(gè)與LoggerConfig關(guān)聯(lián)的名稱(chēng)(通過(guò)name屬性指定),root Logger具有固定的默認(rèn)名稱(chēng),其他Logger需要指定各自的name屬性
值。LoggerConfig會(huì)被分配一個(gè)日志級(jí)別,通過(guò)level屬性來(lái)指定。內(nèi)建的日志級(jí)別按優(yōu)先級(jí)從高到底排序有:OFF > FATAL >
ERROR > WARN > INFO > DEBUG > TRACE > ALL,Log4j 2 也支持自定義的日志級(jí)別。
-->
<Root level="ALL">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLogRollingFile"/>
<AppenderRef ref="WarnLogRollingFile"/>
<AppenderRef ref="DebugLogRollingFile"/>
<AppenderRef ref="ErrorLogRollingFile"/>
</Root>
<!-- 每個(gè)LoggerConfig的日志級(jí)別如果沒(méi)有顯式配置,則會(huì)繼承其父級(jí)LoggerConfig的日志級(jí)別,而root LoggerConfig如果沒(méi)
有配置日志級(jí)別,則會(huì)為其分配一個(gè)默認(rèn)的ERROR級(jí)別 -->
<!-- 某個(gè)Logger所允許的每條日志打印請(qǐng)求都會(huì)傳遞給其LoggerConfig中的所有Appender,也會(huì)傳遞給該LoggerConfig的parent
LoggerConfig中的Appender,這種現(xiàn)象稱(chēng)為相加性(Additivity)。也就是說(shuō),Appender會(huì)從LoggerConfig的繼承中繼承相加性。這種特
性可以用來(lái)匯整某幾個(gè)logger的輸出,可以在聲明Logger的配置文件中設(shè)置additivity="false"來(lái)禁用這種疊加繼承 -->
<!--記錄druid-sql的記錄-->
<Logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="DruidSqlRollingFile"/>
</Logger>
<!--過(guò)濾掉spring和mybatis的一些無(wú)用的DEBUG信息-->
<Logger name="org.springframework" level="INFO"/>
<Logger name="org.mybatis" level="INFO"/>
<!--log4j2 自帶過(guò)濾日志-->
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error"/>
<Logger name="org.apache.catalina.util.LifecycleBase" level="error"/>
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn"/>
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn"/>
<Logger name="org.crsh.plugin" level="warn"/>
<Logger name="org.crsh.ssh" level="warn"/>
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error"/>
<Logger name="org.hibernate.validator.internal.util.Version" level="warn"/>
<Logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="warn"/>
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Logger name="org.thymeleaf" level="warn"/>
</Loggers>
</Configuration>
log4j配置文件詳解
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 記下依賴(lài)包 log4j 有三個(gè)核心功能 日志信息的優(yōu)先級(jí) 日志信息的輸出目的地 日志輸出的格式 而使用配置文件不僅...
- 分享是最好的記憶--如需轉(zhuǎn)發(fā)請(qǐng)注明出處 **[強(qiáng)調(diào)]:共同學(xué)習(xí)** 共同進(jìn)步 不喜勿噴 所需jar包 log4j-...
- 項(xiàng)目jar正常,我們項(xiàng)目log4j中已經(jīng)配置了root日志級(jí)別level為info,但是啟動(dòng)項(xiàng)目后,自定義logg...
- 原文來(lái)自:https://blog.csdn.net/u010544643/article/details/866...