在項目開發(fā)過程中生蚁,我們可以通過 debug 查找問題。而在線上環(huán)境我們查找問題只能通過打印日志的方式查找問題档悠。因此對于一個項目而言,日志記錄是一個非常重要的問題望浩。因此辖所,如何選擇一個合適的日志記錄框架也非常重要。
在Java開發(fā)中曾雕,常用的日志記錄框架有JDKLog奴烙、Log4J、LogBack剖张、SLF4J切诀、SLF4J。這些日志記錄框架各有各的特點搔弄,各有各的應用場景幅虑。了解這些框架的特點及應用場景,有利于我們做技術選型的時候做出正確的判斷顾犹。
獲取更多視頻資料加群:554355695
如果你想學習Java工程化倒庵、高性能及分布式、高性能炫刷、深入淺出擎宝。性能調優(yōu)、Spring浑玛,MyBatis绍申,Netty
源碼分析和大數(shù)據(jù)等知識點可以來找我。
而現(xiàn)在我就有一個平臺可以提供給你們學習顾彰,讓你在實踐中積累經驗掌握原理极阅。主要方向是JAVA架構
師。如果你想拿高薪涨享,想突破瓶頸筋搏,想跟別人競爭能取得優(yōu)勢的,想進BAT但是有擔心面試不過的厕隧,可
以加我的Java架構進階群:554355695
JDKLog:日志小刀
JDKLog是JDK官方提供的一個記錄日志的方式奔脐,直接在JDK中就可以使用。
import java.util.logging.Logger;
/****
** JDKLog Demo
**/
public class JDKLog
{
public static void main( String[] args )
{
Logger logger = Logger.getLogger("JDKLog");
logger.info("Hello World.");
}
}
JDKLog 的有點是使用非常簡單吁讨,直接在 JDK 中就可以使用帖族。但 JDKLog 功能比較太過于簡單,不支持占位符顯示挡爵,拓展性比較差竖般,所以現(xiàn)在用的人也很少。
Log4J:日志大炮
Log4J 是 Apache 的一個日志開源框架茶鹃,有多個分級(DEBUG/INFO/WARN/ERROR)記錄級別涣雕,可以很好地將不同日志級別的日志分開記錄艰亮,極大地方便了日志的查看。
Log4J 有 1.X 版本和 2.X 版本挣郭,現(xiàn)在官方推薦使用 2.X 版本迄埃,2.X 版本在架構上進行了一些升級,配置文件也發(fā)生了一些變化兑障。
使用 Log4J 框架首先需要引入依賴的包:
<!-- Log4J -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
增加配置文件 log4j2.xml 放在 resource 目錄下:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
其中<root style="margin: 0px; padding: 0px;">節(jié)點的 level 屬性表示輸出的最低級別侄非。</root>
最后編寫一個測試類:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/****
** Log4J Demo
**/
public class Log4jLog {
public static void main(String args[]) {
Logger logger = LogManager.getLogger(Log4jLog.class);
logger.debug("Debug Level");
logger.info("Info Level");
logger.warn("Warn Level");
logger.error("Error Level");
}
}
運行測試類輸出結果:
10:16:08.279 [main] INFO com.chanshuyi.Log4jLog - Info Level
10:16:08.280 [main] WARN com.chanshuyi.Log4jLog - Warn Level
10:16:08.280 [main] ERROR com.chanshuyi.Log4jLog - Error Level
如果沒有配置 log4j2.xml 配置文件,那么LOG4J將自動啟用類似于下面的的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
使用默認配置文件的輸出結果:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
11:40:07.377 [main] ERROR com.chanshuyi.Log4jLog - Error Level
從上面的使用步驟可以看出 Log4J 的使用稍微復雜一些流译,但是條理還是很清晰的逞怨。而且因為 Log4J 有多個分級(DEBUG/INFO/WARN/ERROR)記錄級別,所以可以很好地記錄不同業(yè)務問題福澡。因為這些優(yōu)點叠赦,所以在幾年前幾乎所有人都使用 Log4J 作為日志記錄框架,群眾基礎可謂非常深厚革砸。
但 Log4J 本身也存在一些缺點娩践,比如不支持使用占位符墨微,不利于代碼閱讀等缺點。但是相比起 JDKLog厂庇,Log4J 可以說是非常好的日志記錄框架了旦事。
LogBack:日志火箭
LogBack 其實可以說是 Log4J 的進化版档泽,因為它們兩個都是同一個人(Ceki Gülcü)設計的開源日志組件瓣蛀。LogBack 除了具備 Log4j 的所有優(yōu)點之外棕叫,還解決了 Log4J 不能使用占位符的問題。
使用 LogBack 需要首先引入依賴:
<!-- LogBack -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
配置 logback.xml 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<logger name="com.chanshuyi" level="TRACE"/>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
LogBack 的日志級別區(qū)分可以細分到類或者包允耿,這樣就可以使日志記錄變得更加靈活借笙。之后在類文件中引入Logger類扒怖,并進行日志記錄:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/****
** LogBack Demo
**/
public class LogBack {
static final Logger logger = LoggerFactory.getLogger(LogBack.class);
public static void main(String[] args) {
logger.trace("Trace Level.");
logger.debug("Debug Level.");
logger.info("Info Level.");
logger.warn("Warn Level.");
logger.error("Error Level.");
}
}
輸出結果:
14:34:45.747 [main] TRACE com.chanshuyi.LogBack - Trace Level.
14:34:45.749 [main] DEBUG com.chanshuyi.LogBack - Debug Level.
14:34:45.749 [main] INFO com.chanshuyi.LogBack - Info Level.
14:34:45.749 [main] WARN com.chanshuyi.LogBack - Warn Level.
14:34:45.749 [main] ERROR com.chanshuyi.LogBack - Error Level.
LogBack 解決了 Log4J 不能使用占位符的問題较锡,這使得閱讀日志代碼非常方便。除此之外盗痒,LogBack 比 Log4J 有更快的運行速度蚂蕴,更好的內部實現(xiàn)。并且 LogBack 內部集成了 SLF4J 可以更原生地實現(xiàn)一些日志記錄的實現(xiàn)俯邓。
SLF4J:適配器
上面說了 JDKLog骡楼、Log4J、LogBack 這幾個常用的日志記錄框架稽鞭,它們都有各自的優(yōu)缺點鸟整,適合在不同的場景下使用‰蹋可能簡單的項目直接用 JDKLog 就可以了篮条,而復雜的項目需要用上 Log4J弟头。
很多時候我們做項目都是從簡單到復雜,也就是我們很可能一開始使用的是 JDKLog涉茧,之后業(yè)務復雜了需要使用 Log4J赴恨,這時候我們如何將原來寫好的日志用新的日志框架輸出呢?
一個最死板的方法就是一行行代碼修改伴栓,把之前用 JDKLog 的日志代碼全部修改成 Log4J 的日志接口伦连。但是這種方式不僅效率低下,而且做的工作都是重復性的工作钳垮,這怎么能忍呢惑淳。
正式因為在實際的項目應用中,有時候可能會從一個日志框架切換到另外一個日志框架的需求扔枫,這時候往往需要在代碼上進行很大的改動汛聚。為了避免切換日志組件時要改動代碼,這時候一個叫做 SLF4J(Simple Logging Facade for Java短荐,即Java簡單日志記錄接口集)的東西出現(xiàn)了倚舀。
SLF4J(Simple Logging Facade for Java,即Java簡單日志記錄接口集)是一個日志的接口規(guī)范忍宋,它對用戶提供了統(tǒng)一的日志接口痕貌,屏蔽了不同日志組件的差異。這樣我們在編寫代碼的時候只需要看 SLF4J 這個接口文檔即可糠排,不需要去理會不同日之框架的區(qū)別舵稠。而當我們需要更換日志組件的時候,我們只需要更換一個具體的日志組件Jar包就可以了入宦。
而整合 SLF4J 和日志框架使用也是一件很簡單的事情哺徊。
SLF4J+JDKLog
SLF4J + JDKLog 需要在 Maven 中導入以下依賴包:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.21</version>
</dependency>
編寫測試類:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/****
** SLF4J + JDKLog
**/
public class Slf4jJDKLog {
final static Logger logger = LoggerFactory.getLogger(Slf4jJDKLog.class);
public static void main(String[] args) {
logger.trace("Trace Level.");
logger.info("Info Level.");
logger.warn("Warn Level.");
logger.error("Error Level.");
}
}
輸出結果:
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
信息: Info Level.
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
警告: Warn Level.
七月 15, 2016 3:30:02 下午 com.chanshuyi.slf4j.Slf4jJDKLog main
嚴重: Error Level.
SLF4J+LOG4J
需要依賴的 Jar 包:slf4j-api.jar、slf4j-412.jar乾闰、log4j.jar落追,導入Maven依賴:
<!-- 2.SLF4J + Log4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
配置 log4j.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' >
<appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" />
</layout>
<!--過濾器設置輸出的級別-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="debug" />
<param name="levelMax" value="error" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<!-- 根logger的設置-->
<root>
<priority value ="debug"/>
<appender-ref ref="myConsole"/>
</root>
</log4j:configuration>
我們還是用上面的代碼,無需做改變涯肩,運行結果為:
[15 16:04:06,371 DEBUG] [main] slf4j.SLF4JLog - Debug Level.
[15 16:04:06,371 INFO ] [main] slf4j.SLF4JLog - Info Level.
[15 16:04:06,371 WARN ] [main] slf4j.SLF4JLog - Warn Level.
[15 16:04:06,371 ERROR] [main] slf4j.SLF4JLog - Error Level.
SLF4J+LogBack
導入依賴:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.7</version>
</dependency>
配置 logback.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<logger name="com.chanshuyi" level="TRACE"/>
<root level="warn">
<appender-ref ref="STDOUT" />
</root>
</configuration>
我們還是用上面的代碼轿钠,無需做改變,運行結果為:
16:08:01.040 [main] TRACE com.chanshuyi.slf4j.SLF4JLog - Trace Level.
16:08:01.042 [main] DEBUG com.chanshuyi.slf4j.SLF4JLog - Debug Level.
16:08:01.043 [main] INFO com.chanshuyi.slf4j.SLF4JLog - Info Level.
16:08:01.043 [main] WARN com.chanshuyi.slf4j.SLF4JLog - Warn Level.
16:08:01.043 [main] ERROR com.chanshuyi.slf4j.SLF4JLog - Error Level.
LogBack日志框架
經過上面的介紹病苗,相信大家對 Java 常用的日志框架都有了一定認識疗垛。
那么在實際使用中到底選擇哪種日志框架合適呢?
按筆者理解硫朦,現(xiàn)在最流的日志框架解決方案莫過于SLF4J + LogBack贷腕。原因有下面幾點:
- LogBack 自身實現(xiàn)了 SLF4J 的日志接口,不需要 SLF4J 去做進一步的適配。
- LogBack 自身是在 Log4J 的基礎上優(yōu)化而成的泽裳,其運行速度和效率都比 LOG4J 高芽世。
- SLF4J + LogBack 支持占位符,方便日志代碼的閱讀诡壁,而 LOG4J 則不支持济瓢。
從上面幾點來看,SLF4J + LogBack是一個較好的選擇妹卿。
LogBack 被分為3個組件:logback-core旺矾、logback-classic 和 logback-access。
logback-core 提供了 LogBack 的核心功能夺克,是另外兩個組件的基礎箕宙。
logback-classic則實現(xiàn)了 SLF4J 的API,所以當想配合 SLF4J 使用時铺纽,需要將 logback-classic 引入依賴中柬帕。
-
logback-access
是為了集成Servlet環(huán)境而準備的,可提供HTTP-access的日志接口狡门。
LogBack的日志記錄數(shù)據(jù)流是從 Class(Package)到 Logger陷寝,再從Logger到Appender,最后從Appender到具體的輸出終端其馏。
LogBack配置文件可以分為幾個節(jié)點凤跑,其中 Configuration 是根節(jié)點,Appender叛复、Logger仔引、Root是Configuration的子節(jié)點。
appender節(jié)點
<appender style="margin: 0px; padding: 0px;">是<configuration style="margin: 0px; padding: 0px;">的子節(jié)點褐奥,是負責寫日志的組件咖耘。appender有兩個必要屬性name、class 撬码。name指定appender的名稱儿倒,class指定appender的全限定名
class,主要包括:</configuration></appender>
- ch.qos.logback.core.ConsoleAppender 控制臺輸出
- ch.qos.logback.core.FileAppender 文件輸出
- ch.qos.logback.core.RollingFileAppender 文件滾動輸出
<?xml version="1.0" encoding="utf-8"?>
<configuration debug="true" scan="true" scanPeriod="2">
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
</appender>
<!-- conf file out -->
<appender name="file_out" class="ch.qos.logback.core.FileAppender">
</appender>
<!-- conf file out -->
<appender name="file_out" class="ch.qos.logback.core.RollingFileAppender">
</appender>
<root></root>
<logger></logger>
</configuration>
ConsoleAppender
把日志添加到控制臺耍群,有如下節(jié)點:
-
<encoder>
: 對日志進行格式化义桂。
-
<target>
: 字符串System.out 或者 System.err, 默認 System.out;
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date [%thread] %-5level %logger - %message%newline</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console_out" />
</root>
</configuration>
FileAppender
把日志添加到文件找筝,有如下節(jié)點:
-
<file>
:被寫入的文件名,可以是相對目錄 , 也可以是絕對目錄 , 如果目錄不存在則會自動創(chuàng)建蹈垢。 -
<append>
:如果是true , 日志被追加到文件結尾 , 如果是false,清空現(xiàn)存文件 , 默認是true。 -
<encoder>
:對日志進行格式化 [具體的轉換符說明請參見官網(wǎng).]
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appender name="file_out" class="ch.qos.logback.core.FileAppender">
<file>logs/debug.log</file>
<encoder>
<pattern>%date [%thread] %-5level %logger - %message%newline</pattern>
</encoder>
</appender>
</configuration>
rollingFileAppender
滾動紀錄文件袖裕,先將日志記錄到指定文件曹抬,當符合某種條件時,將日志記錄到其他文件急鳄,有如下節(jié)點:
-
<file>
:被寫入的文件名谤民,可以是相對目錄堰酿,也可以解決目錄,如果目錄不存在則自動創(chuàng)建张足。 -
<append>
:如果是true触创,日志被追加到文件結尾,如果是false为牍,清空現(xiàn)存文件哼绑,默認是true。 -
<encoder>
:對日志進行格式化碉咆。 -
<rollingPolicy>
:當發(fā)生滾動時抖韩,決定 RollingFileAppender 的行為,涉及文件移動和重命名疫铜。
rollingPolicy
- TimeBaseRollingPolicy :最常用的滾動策略茂浮,根據(jù)時間來制定滾動策略,即負責滾動也負責觸發(fā)滾動壳咕。有如下節(jié)點席揽;
-
<fileNamePattern>
:必要節(jié)點,包含文件及“%d” 轉換符谓厘,“%d”可以包含一個java.text.SimpleDateFormat 制定的時間格式驹尼,如:%d{yyyy-MM},如果直接使用%d ,默認格式是 yyyy-MM-dd庞呕。 -
<maxHistory>
:可選節(jié)點新翎,控制保留的歸檔文件的最大數(shù)量,超出數(shù)量就刪除舊文件住练,假設設置每個月滾動地啰,且 <maxhistory style="margin: 0px; padding: 0px;">是 6,則只保存最近6個月的文件讲逛,刪除之前的舊文件亏吝,注意:刪除舊文件是哪些為了歸檔而創(chuàng)建的目錄也會被刪除。</maxhistory> -
<filenamePattern>
:必須包含“%i” 例如:設置最小值盏混,和最大值分別為1和2蔚鸥,命名模式為 log%i.log,會產生歸檔文件log1.log和log2.log,還可以指定文件壓縮選項许赃,例如:log%i.log.gz 或者 log%i.log.zip
-
- triggeringPolicy:告知RollingFileAppender止喷,激活RollingFileAppender滾動。
<!-- 03:conf errorAppender out -->
<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/error.log</file>
<!-- 設置滾動策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--設置日志命名模式-->
<fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 超過150MB時混聊,觸發(fā)滾動策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>
logger節(jié)點
logger是<configuration style="margin: 0px; padding: 0px;">的子節(jié)點弹谁,來設置某一個包或者具體的某一個類的日志打印級別,以及指定<appender style="margin: 0px; padding: 0px;">。logger僅有一個name屬性预愤,兩個可選屬性 level/addtivity沟于。</appender></configuration>
- name:用來指定受此loger約束的某一個包或者具體的某一個類。
- level:用來設置打印級別植康,大小寫無關旷太。可選值有TRACE销睁、DEBUG泳秀、INFO、WARN榄攀、ERROR嗜傅、ALL和OFF。還有一個特俗值INHERITED 或者 同義詞NULL檩赢,代表強制執(zhí)行上級的級別吕嘀。如果未設置此屬性,那么當前l(fā)ogger將會繼承上級的級別贞瞒。
- addtivity:是否向上級logger傳遞打印信息偶房,默認為true;
<logger style="margin: 0px; padding: 0px;">可以包含零個或多個<appender-ref style="margin: 0px; padding: 0px;">元素军浆,表示這個appender將會添加到logger棕洋。</appender-ref></logger>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 過濾掉非INFO級別 -->
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- conf infoAppender out -->
<appender name="infoAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/info.log</file>
<!-- 設置滾動策略 -->
<rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--設置日志命名模式-->
<fileNamePattern>infoFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPoliy>
<!-- 超過150MB時,觸發(fā)滾動策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>
<!-- 添加兩個appender節(jié)點 -->
<logger name="logback.olf.log" level="info">
<appender-ref ref = "console_out"/>
<appender-ref ref = "infoAppender"/>
</logger>
</configuration>
root節(jié)點
元素配置根logger乒融。該元素有一個level屬性掰盘,沒有name屬性,因為已經被命名 為root赞季。Level屬性的值大小寫無關愧捕,其值為下面其中一個字符串:TRACE、DEBUG申钩、INFO次绘、 WARN、ERROR撒遣、ALL 和 OFF邮偎。如果 root 元素沒 有引用任何 appender,就會失去所有 appender义黎。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 過濾掉非INFO級別 -->
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 01:conf infoAppender out -->
<appender name="infoAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/info.log</file>
<!-- 設置滾動策略 -->
<rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--設置日志命名模式-->
<fileNamePattern>infoFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPoliy>
<!-- 超過150MB時禾进,觸發(fā)滾動策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>
<!-- 02:conf debugAppender out -->
<appender name="debugAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/debug.log</file>
<!-- 設置滾動策略 -->
<rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--設置日志命名模式-->
<fileNamePattern>debugFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPoliy>
<!-- 超過150MB時,觸發(fā)滾動策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>
<!-- 03:conf errorAppender out -->
<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/error.log</file>
<!-- 設置滾動策略 -->
<rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--設置日志命名模式-->
<fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPoliy>
<!-- 超過150MB時轩缤,觸發(fā)滾動策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>
<root level="ALL">
<appender-ref ref="infoAppender"/>
<appender-ref ref="debugAppender"/>
<appender-ref ref="errorAppender"/>
</root>
</configuration>
filter過濾節(jié)點
級別過濾器(LevelFilter)
LevelFilter 根據(jù)記錄級別對記錄事件進行過濾命迈。如果事件的級別等于配置的級別,過濾 器會根據(jù) onMatch 和 onMismatch 屬性接受或拒絕事件火的。下面是個配置文件例子:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 過濾掉非INFO級別 -->
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console_out" />
</root>
</configuration>
臨界值過濾器(ThresholdFilter)
ThresholdFilter過濾掉低于指定臨界值的事件壶愤。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 過濾掉TRACE和DEBUG級別的日志 -->
<level>INFO</level>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console_out" />
</root>
</configuration>
求值過濾器(EvaluatorFilter)
評估是否符合指定的條件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.EvaluatorFilter">
<evaluator>
<!--過濾掉所有日志中不包含hello字符的日志-->
<expression>
message.contains("hello")
</expression>
<onMatch>NEUTRAL</onMatch>
<onMismatch>DENY</onMismatch>
</evaluator>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console_out" />
</root>
</configuration>
匹配器(Matchers)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.EvaluatorFilter">
<evaluator>
<matcher>
<Name>odd</Name>
<!-- 過濾掉序號為奇數(shù)的語句-->
<regex>statement [13579]</regex>
</matcher>
<expression>odd.matches(formattedMessage)</expression>
<onMatch>NEUTRAL</onMatch>
<onMismatch>DENY</onMismatch>
</evaluator>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="console_out" />
</root>
</configuration>
下面是一個我常用的logback.xml配置文件,供大家參考:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - %m%n</pattern>
<!-- 常用的Pattern變量,大家可打開該pattern進行輸出觀察 -->
<!--
<pattern>
%d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n
Logger: %logger
Class: %class
File: %file
Caller: %caller
Line: %line
Message: %m
Method: %M
Relative: %relative
Thread: %thread
Exception: %ex
xException: %xEx
nopException: %nopex
rException: %rEx
Marker: %marker
%n
</pattern>
-->
</encoder>
</appender>
<!-- 按日期區(qū)分的滾動日志 -->
<appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/error.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>error.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<!-- 按文件大小區(qū)分的滾動日志 -->
<appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/info.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>info.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
</appender>
<!-- 按日期和大小區(qū)分的滾動日志 -->
<appender name="DEBUG-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/debug.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!-- 級別閥值過濾 -->
<appender name="SUM-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/sum.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder>
<!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="ERROR-OUT" />
<appender-ref ref="INFO-OUT" />
<appender-ref ref="DEBUG-OUT" />
<appender-ref ref="SUM-OUT" />
</root>
</configuration>
如何進行日志系統(tǒng)轉換馏鹤?
在實際的日志轉換過程中征椒,SLF4J其實是充當了一個中介的角色。例如當我們一個項目原來是使用LOG4J進行日志記錄湃累,但是我們要換成LogBack進行日志記錄勃救。
此時我們需要先將LOG4J轉換成SLF4J日志系統(tǒng),再從SLF4J日志系統(tǒng)轉成LogBack日志系統(tǒng)治力。
從日志框架轉向SLF4J
- jul-to-slf4j:jdk-logging到slf4j的橋梁
- log4j-over-slf4j:log4j1到slf4j的橋梁
- jcl-over-slf4j:commons-logging到slf4j的橋梁
從SLF4J轉向具體的日志框架
- slf4j-jdk14:slf4j到jdk-logging的橋梁
- slf4j-log4j12:slf4j到log4j1的橋梁
- log4j-slf4j-impl:slf4j到log4j2的橋梁
- logback-classic:slf4j到logback的橋梁
- slf4j-jcl:slf4j到commons-logging的橋梁
例如我們一開始使用的是 Log4J 日志框架蒙秒,現(xiàn)在我們希望轉成 LogBack 框架,那么我們首先需要加入 log4j-over-slf4j.jar 將 Log4J 轉成 SLF4J宵统,之后再加入 logback-classic.jar 將 SLF4J 轉成 LogBack晕讲。
日志技術框架一覽
- JUL:JDK中的日志記錄工具,也常稱為JDKLog马澈、jdk-logging瓢省。
- LOG4J1:一個具體的日志實現(xiàn)框架。
- LOG4J2:一個具體的日志實現(xiàn)框架痊班,是LOG4J1的下一個版本勤婚。
- LOGBACK:一個具體的日志實現(xiàn)框架,但其性能更好涤伐。
- JCL:一個日志門面馒胆,提供統(tǒng)一的日志記錄接口,也常稱為commons-logging凝果。
- SLF4J:一個日志門面国章,與JCL一樣提供統(tǒng)一的日志記錄接口,可以方便地切換看具體的實現(xiàn)框架豆村。
JUL液兽、LOG4J1、LOG4J2掌动、LOGBACK是日志實現(xiàn)框架四啰,而JCL、SLF4J是日志實現(xiàn)門面粗恢。