电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java日志框架之logback使用詳解

瀏覽:7日期:2022-08-27 16:42:28

為什么使用logback

記得前幾年工作的時(shí)候,公司使用的日志框架還是log4j,大約從16年中到現(xiàn)在,不管是我參與的別人已經(jīng)搭建好的項(xiàng)目還是我自己主導(dǎo)的項(xiàng)目,日志框架基本都換成了logback,總結(jié)一下,logback大約有以下的一些優(yōu)點(diǎn):

內(nèi)核重寫(xiě)、測(cè)試充分、初始化內(nèi)存加載更小,這一切讓logback性能和log4j相比有諸多倍的提升 logback非常自然地直接實(shí)現(xiàn)了slf4j,這個(gè)嚴(yán)格來(lái)說(shuō)算不上優(yōu)點(diǎn),只是這樣,再理解slf4j的前提下會(huì)很容易理解logback,也同時(shí)很容易用其他日志框架替換logback logback有比較齊全的200多頁(yè)的文檔 logback當(dāng)配置文件修改了,支持自動(dòng)重新加載配置文件,掃描過(guò)程快且安全,它并不需要另外創(chuàng)建一個(gè)掃描線程 支持自動(dòng)去除舊的日志文件,可以控制已經(jīng)產(chǎn)生日志文件的最大數(shù)量

總而言之,如果大家的項(xiàng)目里面需要選擇一個(gè)日志框架,那么我個(gè)人非常建議使用logback。

logback加載

我們簡(jiǎn)單分析一下logback加載過(guò)程,當(dāng)我們使用logback-classic.jar時(shí),應(yīng)用啟動(dòng),那么logback會(huì)按照如下順序進(jìn)行掃描:

在系統(tǒng)配置文件System Properties中尋找是否有l(wèi)ogback.configurationFile對(duì)應(yīng)的value 在classpath下尋找是否有l(wèi)ogback.groovy(即logback支持groovy與xml兩種配置方式) 在classpath下尋找是否有l(wèi)ogback-test.xml 在classpath下尋找是否有l(wèi)ogback.xml

以上任何一項(xiàng)找到了,就不進(jìn)行后續(xù)掃描,按照對(duì)應(yīng)的配置進(jìn)行l(wèi)ogback的初始化,具體代碼實(shí)現(xiàn)可見(jiàn)ch.qos.logback.classic.util.ContextInitializer類的findURLOfDefaultConfigurationFile方法。

當(dāng)所有以上四項(xiàng)都找不到的情況下,logback會(huì)調(diào)用ch.qos.logback.classic.BasicConfigurator的configure方法,構(gòu)造一個(gè)ConsoleAppender用于向控制臺(tái)輸出日志,默認(rèn)日志輸出格式為'%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n'。

logback的configuration

logback的重點(diǎn)應(yīng)當(dāng)是Appender、Logger、Pattern,在這之前先簡(jiǎn)單了解一下logback的<configuration>,<configuration>只有三個(gè)屬性:

scan:當(dāng)scan被設(shè)置為true時(shí),當(dāng)配置文件發(fā)生改變,將會(huì)被重新加載,默認(rèn)為true scanPeriod:檢測(cè)配置文件是否有修改的時(shí)間間隔,如果沒(méi)有給出時(shí)間單位,默認(rèn)為毫秒,當(dāng)scan=true時(shí)這個(gè)值生效,默認(rèn)時(shí)間間隔為1分鐘 debug:當(dāng)被設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行信息,默認(rèn)為false

<logger>與<root>

先從最基本的<logger>與<root>開(kāi)始。

<logger>用來(lái)設(shè)置某一個(gè)包或者具體某一個(gè)類的日志打印級(jí)別、以及指定<appender>。<logger>可以包含零個(gè)或者多個(gè)<appender-ref>元素,標(biāo)識(shí)這個(gè)appender將會(huì)添加到這個(gè)logger。<logger>僅有一個(gè)name屬性、一個(gè)可選的level屬性和一個(gè)可選的additivity屬性:

name:用來(lái)指定受此logger約束的某一個(gè)包或者具體的某一個(gè)類 level:用來(lái)設(shè)置打印級(jí)別,五個(gè)常用打印級(jí)別從低至高依次為T(mén)RACE、DEBUG、INFO、WARN、ERROR,如果未設(shè)置此級(jí)別,那么當(dāng)前l(fā)ogger會(huì)繼承上級(jí)的級(jí)別 additivity:是否向上級(jí)logger傳遞打印信息,默認(rèn)為true

<root>也是<logger>元素,但是它是根logger,只有一個(gè)level屬性,因?yàn)樗膎ame就是ROOT,關(guān)于這個(gè)地方,有朋友微信上問(wèn)起,源碼在LoggerContext中:

public LoggerContext() { super(); this.loggerCache = new ConcurrentHashMap<String, Logger>(); this.loggerContextRemoteView = new LoggerContextVO(this); this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this); this.root.setLevel(Level.DEBUG); loggerCache.put(Logger.ROOT_LOGGER_NAME, root); initEvaluatorMap(); size = 1; this.frameworkPackages = new ArrayList<String>();}

Logger的構(gòu)造函數(shù)為:

Logger(String name, Logger parent, LoggerContext loggerContext) { this.name = name; this.parent = parent; this.loggerContext = loggerContext;}

看到第一個(gè)參數(shù)就是Root的name,而這個(gè)Logger.ROOT_LOGGER_NAME的定義為final public String ROOT_LOGGER_NAME = 'ROOT',由此可以看出<root>節(jié)點(diǎn)的name就是'ROOT'。

接著寫(xiě)一段代碼來(lái)測(cè)試一下:

public class Slf4jTest { @Test public void testSlf4j() { Logger logger = LoggerFactory.getLogger(Object.class); logger.trace('=====trace====='); logger.debug('=====debug====='); logger.info('=====info====='); logger.warn('=====warn====='); logger.error('=====error====='); }}

logback.xml的配置為:

<?xml version='1.0' encoding='UTF-8' ?><configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <layout class='ch.qos.logback.classic.PatternLayout'> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </layout> </appender> <root level='info'> <appender-ref ref='STDOUT' /> </root></configuration>

root將打印級(jí)別設(shè)置為'info'級(jí)別,<appender>暫時(shí)不管,控制臺(tái)的輸出為:

2018-03-26 22:57:48.779 [main] INFO java.lang.Object - =====info=====2018-03-26 22:57:48.782 [main] WARN java.lang.Object - =====warn=====2018-03-26 22:57:48.782 [main] ERROR java.lang.Object - =====error=====

logback.xml的意思是,當(dāng)Test方法運(yùn)行時(shí),root節(jié)點(diǎn)將日志級(jí)別大于等于info的交給已經(jīng)配置好的名為'STDOUT'的<appender>進(jìn)行處理,'STDOUT'將信息打印到控制臺(tái)上。

接著理解一下<logger>節(jié)點(diǎn)的作用,logback.xml修改一下,加入一個(gè)只有name屬性的<logger>:

<?xml version='1.0' encoding='UTF-8' ?><configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <layout class='ch.qos.logback.classic.PatternLayout'> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </layout> </appender> <logger name='java' /> <root level='debug'> <appender-ref ref='STDOUT' /> </root></configuration>

注意這個(gè)name表示的是LoggerFactory.getLogger(XXX.class),XXX的包路徑,包路徑越少越是父級(jí),我們測(cè)試代碼里面是Object.class,即name='java'是name='java.lang'的父級(jí),root是所有<logger>的父級(jí)。看一下輸出為:

2018-03-27 23:02:02.963 [main] DEBUG java.lang.Object - =====debug=====2018-03-27 23:02:02.965 [main] INFO java.lang.Object - =====info=====2018-03-27 23:02:02.966 [main] WARN java.lang.Object - =====warn=====2018-03-27 23:02:02.966 [main] ERROR java.lang.Object - =====error=====

出現(xiàn)這樣的結(jié)果是因?yàn)椋?/p> <logger>中沒(méi)有配置level,即繼承父級(jí)的level,<logger>的父級(jí)為<root>,那么level=debug 沒(méi)有配置additivity,那么additivity=true,表示此<logger>的打印信息向父級(jí)<root>傳遞 沒(méi)有配置<appender-ref>,表示此<logger>不會(huì)打印出任何信息

由此可知,<logger>的打印信息向<root>傳遞,<root>使用'STDOUT'這個(gè)<appender>打印出所有大于等于debug級(jí)別的日志。舉一反三,我們將<logger>的additivity配置為false,那么控制臺(tái)應(yīng)該不會(huì)打印出任何日志,因?yàn)?lt;logger>的打印信息不會(huì)向父級(jí)<root>傳遞且<logger>沒(méi)有配置任何<appender>,大家可以自己試驗(yàn)一下。

接著,我們?cè)倥渲靡粋€(gè)<logger>:

<?xml version='1.0' encoding='UTF-8' ?><configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <layout class='ch.qos.logback.classic.PatternLayout'> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </layout> </appender> <logger name='java' additivity='false' /> <logger name='java.lang' level='warn'> <appender-ref ref='STDOUT' /> </logger> <root level='debug'> <appender-ref ref='STDOUT' /> </root></configuration>

如果讀懂了上面的例子,那么這個(gè)例子應(yīng)當(dāng)很好理解:

LoggerFactory.getLogger(Object.class),首先找到name='java.lang'這個(gè)<logger>,將日志級(jí)別大于等于warn的使用'STDOUT'這個(gè)<appender>打印出來(lái) name='java.lang'這個(gè)<logger>沒(méi)有配置additivity,那么additivity=true,打印信息向上傳遞,傳遞給父級(jí)name='java'這個(gè)<logger> name='java'這個(gè)<logger>的additivity=false且不關(guān)聯(lián)任何<appender>,那么name='java'這個(gè)<appender>不會(huì)打印任何信息

由此分析,得出最終的打印結(jié)果為:

2018-03-27 23:12:16.147 [main] WARN java.lang.Object - =====warn=====2018-03-27 23:12:16.150 [main] ERROR java.lang.Object - =====error=====

舉一反三,上面的name='java'這個(gè)<appender>可以把a(bǔ)dditivity設(shè)置為true試試看是什么結(jié)果,如果對(duì)前面的分析理解的朋友應(yīng)該很容易想到,有兩部分日志輸出,一部分是日志級(jí)別大于等于warn的、一部分是日志級(jí)別大于等于debug的。

<appender>

接著看一下<appender>,<appender>是<configuration>的子節(jié)點(diǎn),是負(fù)責(zé)寫(xiě)日志的組件。<appender>有兩個(gè)必要屬性name和class:

name指定<appender>的名稱 class指定<appender>的全限定名

<appender>有好幾種,上面我們演示過(guò)的是ConsoleAppender,ConsoleAppender的作用是將日志輸出到控制臺(tái),配置示例為:

<appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender>

其中,encoder表示對(duì)參數(shù)進(jìn)行格式化。我們和上一部分的例子對(duì)比一下,發(fā)現(xiàn)這里是有所區(qū)別的,上面使用了<layout>定義<pattern>,這里使用了<encoder>定義<pattern>,簡(jiǎn)單說(shuō)一下:

<encoder>是0.9.19版本之后引進(jìn)的,以前的版本使用<layout>,logback極力推薦的是使用<encoder>而不是<layout> 最常用的FileAppender和它的子類的期望是使用<encoder>而不再使用<layout>

關(guān)于<encoder>中的格式下一部分再說(shuō)。接著我們看一下FileAppender,F(xiàn)ileAppender的作用是將日志寫(xiě)到文件中,配置示例為:

<appender name='FILE' class='ch.qos.logback.core.FileAppender'> <file>D:/123.log</file> <append>true</append> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder></appender>

它的幾個(gè)節(jié)點(diǎn)為:

<file>表示寫(xiě)入的文件名,可以使相對(duì)目錄也可以是絕對(duì)目錄,如果上級(jí)目錄不存在則自動(dòng)創(chuàng)建 <appender>如果為true表示日志被追加到文件結(jié)尾,如果是false表示清空文件 <encoder>表示輸出格式,后面說(shuō) <prudent>如果為true表示日志會(huì)被安全地寫(xiě)入文件,即使其他的FileAppender也在向此文件做寫(xiě)入操作,效率低,默認(rèn)為false

接著來(lái)看一下RollingFileAppender,RollingFileAppender的作用是滾動(dòng)記錄文件,先將日志記錄到指定文件,當(dāng)符合某個(gè)條件時(shí)再將日志記錄到其他文件,RollingFileAppender配置比較靈活,因此使用得更多,示例為:

<appender name='ROLLING-FILE-1' class='ch.qos.logback.core.rolling.RollingFileAppender'> <rollingPolicy class='ch.qos.logback.core.rolling.TimeBasedRollingPolicy'> <fileNamePattern>rolling-file-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder></appender>

這種是僅僅指定了<rollingPolicy>的寫(xiě)法,<rollingPolicy>的作用是當(dāng)發(fā)生滾動(dòng)時(shí),定義RollingFileAppender的行為,其中上面的TimeBasedRollingPolicy是最常用的滾動(dòng)策略,它根據(jù)時(shí)間指定滾動(dòng)策略,既負(fù)責(zé)滾動(dòng)也負(fù)責(zé)觸發(fā)滾動(dòng),有以下節(jié)點(diǎn):

<fileNamePattern>,必要節(jié)點(diǎn),包含文件名及'%d'轉(zhuǎn)換符,'%d'可以包含一個(gè)Java.text.SimpleDateFormat指定的時(shí)間格式,如%d{yyyy-MM},如果直接使用%d那么格式為yyyy-MM-dd。RollingFileAppender的file子節(jié)點(diǎn)可有可無(wú),通過(guò)設(shè)置file可以為活動(dòng)文件和歸檔文件指定不同的位置 <maxHistory>,可選節(jié)點(diǎn),控制保留的歸檔文件的最大數(shù)量,如果超出數(shù)量就刪除舊文件,假設(shè)設(shè)置每個(gè)月滾動(dòng)且<maxHistory>是6,則只保存最近6個(gè)月的文件

向其他還有SizeBasedTriggeringPolicy,用于按照文件大小進(jìn)行滾動(dòng),可以自己查閱一下資料。

異步寫(xiě)日志

日志通常來(lái)說(shuō)都以文件形式記錄到磁盤(pán),例如使用<RollingFileAppender>,這樣的話一次寫(xiě)日志就會(huì)發(fā)生一次磁盤(pán)IO,這對(duì)于性能是一種損耗,因此更多的,對(duì)于每次請(qǐng)求必打的日志(例如請(qǐng)求日志,記錄請(qǐng)求API、參數(shù)、請(qǐng)求時(shí)間),我們會(huì)采取異步寫(xiě)日志的方式而不讓此次寫(xiě)日志發(fā)生磁盤(pán)IO,阻塞線程從而造成不必要的性能損耗。(不要小看這個(gè)點(diǎn),可以網(wǎng)上查一下服務(wù)端性能優(yōu)化的文章,只是因?yàn)閷⑷罩靖臑楫惒綄?xiě),整個(gè)QPS就有了大幅的提高)。

接著我們看下如何使用logback進(jìn)行異步寫(xiě)日志配置:

<?xml version='1.0' encoding='UTF-8' ?><configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <appender name='ROLLING-FILE-1' class='ch.qos.logback.core.rolling.RollingFileAppender'> <rollingPolicy class='ch.qos.logback.core.rolling.TimeBasedRollingPolicy'> <fileNamePattern>D:/rolling-file-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %lo{35} - %msg%n</pattern> </encoder> </appender> <!-- 異步輸出 --> <appender name ='ASYNC' class= 'ch.qos.logback.classic.AsyncAppender'> <!-- 不丟失日志.默認(rèn)的,如果隊(duì)列的80%已滿,則會(huì)丟棄TRACT、DEBUG、INFO級(jí)別的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默認(rèn)的隊(duì)列的深度,該值會(huì)影響性能.默認(rèn)值為256 --> <queueSize>256</queueSize> <!-- 添加附加的appender,最多只能添加一個(gè) --> <appender-ref ref ='ROLLING-FILE-1'/> </appender> <logger name='java' additivity='false' /> <logger name='java.lang' level='DEBUG'> <appender-ref ref='ASYNC' /> </logger> <root level='INFO'> <appender-ref ref='STDOUT' /> </root></configuration>

即,我們引入了一個(gè)AsyncAppender,先說(shuō)一下AsyncAppender的原理,再說(shuō)一下幾個(gè)參數(shù):

當(dāng)我們配置了AsyncAppender,系統(tǒng)啟動(dòng)時(shí)會(huì)初始化一條名為'AsyncAppender-Worker-ASYNC'的線程當(dāng)Logging Event進(jìn)入AsyncAppender后,AsyncAppender會(huì)調(diào)用appender方法,appender方法中再將event填入Buffer(使用的Buffer為BlockingQueue,具體實(shí)現(xiàn)為ArrayBlockingQueye)前,會(huì)先判斷當(dāng)前Buffer的容量以及丟棄日志特性是否開(kāi)啟,當(dāng)消費(fèi)能力不如生產(chǎn)能力時(shí),AsyncAppender會(huì)將超出Buffer容量的Logging Event的級(jí)別進(jìn)行丟棄,作為消費(fèi)速度一旦跟不上生產(chǎn)速度導(dǎo)致Buffer溢出處理的一種方式。上面的線程的作用,就是從Buffer中取出Event,交給對(duì)應(yīng)的appender進(jìn)行后面的日志推送從上面的描述我們可以看出,AsyncAppender并不處理日志,只是將日志緩沖到一個(gè)BlockingQueue里面去,并在內(nèi)部創(chuàng)建一個(gè)工作線程從隊(duì)列頭部獲取日志,之后將獲取的日志循環(huán)記錄到附加的其他appender上去,從而達(dá)到不阻塞主線程的效果。因此AsyncAppender僅僅充當(dāng)?shù)氖鞘录D(zhuǎn)發(fā)器,必須引用另外一個(gè)appender來(lái)做事。

從上述原理,我們就能比較清晰地理解幾個(gè)參數(shù)的作用了:

discardingThreshold,假如等于20則表示,表示當(dāng)還剩20%容量時(shí),將丟棄TRACE、DEBUG、INFO級(jí)別的Event,只保留WARN與ERROR級(jí)別的Event,為了保留所有的events,可以將這個(gè)值設(shè)置為0,默認(rèn)值為queueSize/5 queueSize比較好理解,BlockingQueue的最大容量,默認(rèn)為256 includeCallerData表示是否提取調(diào)用者數(shù)據(jù),這個(gè)值被設(shè)置為true的代價(jià)是相當(dāng)昂貴的,為了提升性能,默認(rèn)當(dāng)event被加入BlockingQueue時(shí),event關(guān)聯(lián)的調(diào)用者數(shù)據(jù)不會(huì)被提取,只有線程名這些比較簡(jiǎn)單的數(shù)據(jù) appender-ref表示AsyncAppender使用哪個(gè)具體的<appender>進(jìn)行日志輸出

<encoder>

<encoder>節(jié)點(diǎn)負(fù)責(zé)兩件事情:

把日志信息轉(zhuǎn)換為字節(jié)數(shù)組 把字節(jié)數(shù)組寫(xiě)到輸出流

目前PatternLayoutEncoder是唯一有用的且默認(rèn)的encoder,有一個(gè)<pattern>節(jié)點(diǎn),就像上面演示的,用來(lái)設(shè)置日志的輸入格式,使用“%+轉(zhuǎn)換符'的方式,如果要輸出'%'則必須使用'%'對(duì)'%'進(jìn)行轉(zhuǎn)義。

<encoder>的一些可用參數(shù)用表格表示一下:

轉(zhuǎn)換符 作 用 是否避免使用

c{length}

lo{length}

logger{length}

輸出日志的logger名稱,可有一個(gè)整型參數(shù)來(lái)縮短<logger>名稱,有幾種情況:

1、不輸入表示輸出完整的<logger>名稱

2、輸入0表示只輸出<logger>最右邊點(diǎn)號(hào)之后的字符串

3、輸入其他數(shù)字表示輸出小數(shù)點(diǎn)最后邊點(diǎn)號(hào)之前的字符數(shù)量

C{length}

class{length}

輸出指定記錄的請(qǐng)求的調(diào)用者的全限定名,length同上 是

d{pattern}

date{pattern}

輸出時(shí)間格式,模式語(yǔ)法同java.text.SimpleDateFormat兼容 否 caller{depth} 輸出生成日志的調(diào)用者的位置信息,整數(shù)選項(xiàng)表示輸出信息深度 否 L 輸出執(zhí)行日志的請(qǐng)求行號(hào) 是

m

msg

message

輸出應(yīng)用程序提供的信息 否 m 輸入執(zhí)行日志請(qǐng)求的方法名 是 n 輸出平臺(tái)相關(guān)的分行符'n'或者'rn',即換行 否

p

le

level

輸出日志級(jí)別 否

r

relative

輸出從程序啟動(dòng)到創(chuàng)建日志記錄的時(shí)間,單位為毫秒 否

t

thread

輸出產(chǎn)生日志的線程名稱 否

Filter

最后來(lái)看一下<filter>,<filter>是<appender>的一個(gè)子節(jié)點(diǎn),表示在當(dāng)前給到的日志級(jí)別下再進(jìn)行一次過(guò)濾,最基本的Filter有ch.qos.logback.classic.filter.LevelFilter和ch.qos.logback.classic.filter.ThresholdFilter,首先看一下LevelFilter:

<configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> <filter class='ch.qos.logback.classic.filter.LevelFilter'> <level>WARN</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <logger name='java' additivity='false' /> <logger name='java.lang' level='DEBUG'> <appender-ref ref='STDOUT' /> </logger> <root level='INFO'> <appender-ref ref='STDOUT' /> </root></configuration>

看一下輸出:

2018-03-31 22:22:58.843 [main] WARN java.lang.Object - =====warn=====

看到盡管<logger>配置的是DEBUG,但是輸出的只有warn,因?yàn)樵?lt;filter>中對(duì)匹配到WARN級(jí)別時(shí)做了ACCEPT(接受),對(duì)未匹配到WARN級(jí)別時(shí)做了DENY(拒絕),當(dāng)然只能打印出WARN級(jí)別的日志。

再看一下ThresholdFilter,配置為:

<?xml version='1.0' encoding='UTF-8' ?><configuration scan='false' scanPeriod='60000' debug='false'> <appender name='STDOUT' class='ch.qos.logback.core.ConsoleAppender'> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> </encoder> <filter class='ch.qos.logback.classic.filter.ThresholdFilter'> <level>INFO</level> </filter> </appender> <logger name='java' additivity='false' /> <logger name='java.lang' level='DEBUG'> <appender-ref ref='STDOUT' /> </logger> <root level='INFO'> <appender-ref ref='STDOUT' /> </root></configuration>

看一下輸出為:

2018-03-31 22:41:32.353 [main] INFO java.lang.Object - =====info=====2018-03-31 22:41:32.358 [main] WARN java.lang.Object - =====warn=====2018-03-31 22:41:32.359 [main] ERROR java.lang.Object - =====error=====

因?yàn)門(mén)hresholdFilter的策略是,會(huì)將日志級(jí)別小于<level>的全部進(jìn)行過(guò)濾,因此雖然指定了DEBUG級(jí)別,但是只有INFO及以上級(jí)別的才能被打印出來(lái)。

到此這篇關(guān)于Java日志框架之logback使用詳解的文章就介紹到這了,更多相關(guān)Java日志框架logback內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | 工业电炉,台车式电炉_厂家-淄博申华工业电炉有限公司 | 工业PH计|工业ph酸度计|在线PH计价格-合肥卓尔仪器仪表有限公司 济南画室培训-美术高考培训-山东艺霖艺术培训画室 | 间苯二酚,间苯二酚厂家-淄博双和化工 | 散热器-电子散热器-型材散热器-电源散热片-镇江新区宏图电子散热片厂家 | 北京浩云律师事务所-企业法律顾问_破产清算等公司法律服务 | 防水试验机_防水测试设备_防水试验装置_淋雨试验箱-广州岳信试验设备有限公司 | 进口便携式天平,外校_十万分之一分析天平,奥豪斯工业台秤,V2000防水秤-重庆珂偌德科技有限公司(www.crdkj.com) | 智慧食堂_食堂管理系统_食堂订餐_食堂消费系统—客易捷 | 胶泥瓷砖胶,轻质粉刷石膏,嵌缝石膏厂家,腻子粉批发,永康家德兴,永康市家德兴建材厂 | 无轨电动平车_轨道平车_蓄电池电动平车★尽在新乡百特智能转运设备有限公司 | 医学模型生产厂家-显微手术模拟训练器-仿真手术模拟训练系统-北京医教科技 | 福州甲醛检测-福建室内空气检测_环境检测_水质检测-福建中凯检测技术有限公司 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | 代写标书-专业代做标书-商业计划书代写「深圳卓越创兴公司」 | 长沙广告公司_制作,长沙喷绘_发光字_招牌制作_长沙泓润广告官网 长城人品牌官网 | 仓储笼_金属箱租赁_循环包装_铁网箱_蝴蝶笼租赁_酷龙仓储笼租赁 测试治具|过炉治具|过锡炉治具|工装夹具|测试夹具|允睿自动化设备 | 帽子厂家_帽子工厂_帽子定做_义乌帽厂_帽厂_制帽厂_帽子厂_浙江高普制帽厂 | 高效节能电机_伺服主轴电机_铜转子电机_交流感应伺服电机_图片_型号_江苏智马科技有限公司 | 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 铝扣板-铝方通-铝格栅-铝条扣板-铝单板幕墙-佳得利吊顶天花厂家 elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 定坤静电科技静电消除器厂家-除静电设备 | 【灵硕展览集团】展台展会设计_展览会展台搭建_展览展示设计一站式服务公司 | 南京欧陆电气股份有限公司-风力发电机官网| 奥因-光触媒除甲醛公司-除甲醛加盟公司十大品牌 | 耐火浇注料-喷涂料-浇注料生产厂家_郑州市元领耐火材料有限公司 耐力板-PC阳光板-PC板-PC耐力板 - 嘉兴赢创实业有限公司 | Safety light curtain|Belt Sway Switches|Pull Rope Switch|ultrasonic flaw detector-Shandong Zhuoxin Machinery Co., Ltd | 粒米特测控技术(上海)有限公司-测功机_减速机测试台_电机测试台 | 400电话_400电话申请_888元包年_400电话办理服务中心_400VIP网 | 福尔卡(北京)新型材料技术股份有限公司| 体视显微镜_荧光生物显微镜_显微镜报价-微仪光电生命科学显微镜有限公司 | AGV叉车|无人叉车|AGV智能叉车|AGV搬运车-江西丹巴赫机器人股份有限公司 | 云南丰泰挖掘机修理厂-挖掘机维修,翻新,再制造的大型企业-云南丰泰工程机械维修有限公司 | 德国进口电锅炉_商用电热水器_壁挂炉_电采暖器_电热锅炉[德国宝] | 酒精检测棒,数显温湿度计,酒安酒精测试仪,酒精检测仪,呼气式酒精检测仪-郑州欧诺仪器有限公司 | 哔咔漫画网页版在线_下载入口访问指引 | 耙式干燥机_真空耙式干燥机厂家-无锡鹏茂化工装备有限公司 | 水篦子|雨篦子|镀锌格栅雨水篦子|不锈钢排水篦子|地下车库水箅子—安平县云航丝网制品厂 | 我车网|我关心的汽车资讯_汽车图片_汽车生活! | 空气能采暖,热泵烘干机,空气源热水机组|设备|厂家,东莞高温热泵_正旭新能源 | 阀门智能定位器_电液动执行器_气动执行机构-赫尔法流体技术(北京)有限公司 |