日誌的做用是用來追蹤和記錄咱們的程序運行中的信息,咱們能夠利用日誌很快定位問題,追蹤分析。java
首先要知道日誌級別是幹什麼用的,日誌級別是當你使用不一樣的方式運行的時候,根據你運行的方式和你設置的日誌打印級別來肯定哪些信息須要輸出。
規定:日誌只會打印設置的優先級及比本身高優先級的內容。
日誌級別優先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALLweb
Sun公司的日誌框架,原生的日誌框架,優勢是使用很是簡單,直接在 JDK 中就可使用。但 JDKLog 功能比較太過於簡單,不支持佔位符顯示,拓展性比較差,因此如今用的人也不多。 示例:apache
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.");
}
}
複製代碼
Apache的日誌框架,有多個分級(DEBUG/INFO/WARN/ERROR)記錄級別,能夠很好地將不一樣日誌級別的日誌分開記錄,極大地方便了日誌的查看。api
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
複製代碼
### 設置###
log4j.rootLogger = debug,stdout,D,E
### 輸出信息到控制擡 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 輸出DEBUG 級別以上的日誌到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 輸出ERROR 級別以上的日誌到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
複製代碼
Log4j升級版,2.x的版本在架構上進行了一些升級,配置文件也發生了一些變化。bash
<!-- 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>
複製代碼
注:log4j和log4j2的依賴包路徑是不同的,這是爲了區分log4j和log4j2,開發者專門設置的。架構
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="error">
<!-- 先定義全部的appender -->
<appenders>
<!-- 這個輸出控制檯的配置 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 控制檯只輸出level及以上級別的信息(onMatch),其餘的直接拒絕(onMismatch) -->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 這個都知道是輸出日誌的格式 -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</Console>
<!-- 文件會打印出全部信息,這個log每次運行程序會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用 -->
<!-- append爲TRUE表示消息增長到指定文件中,false表示消息覆蓋指定的文件內容,默認值是true -->
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 添加過濾器ThresholdFilter,能夠有選擇的輸出某個級別以上的類別 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,不然直接拒絕 -->
<File name="ERROR" fileName="logs/error.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 這個會打印出全部的信息,每次大小超過size,則這size大小的日誌會自動存入按年份-月份創建的文件夾下面並進行壓縮,做爲存檔 -->
<RollingFile name="RollingFile" fileName="logs/web.log"
filePattern="logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="2MB"/>
</RollingFile>
</appenders>
<!-- 而後定義logger,只有定義了logger並引入的appender,appender纔會生效 -->
<loggers>
<!-- 創建一個默認的root的logger -->
<root level="trace">
<appender-ref ref="RollingFile"/>
<appender-ref ref="Console"/>
<appender-ref ref="ERROR" />
<appender-ref ref="log"/>
</root>
</loggers>
</configuration>
複製代碼
日誌門面,支持運行時動態加載日誌組件實現。也就是說,在應用代碼中,只須要調用commons logging的接口,底層實現能夠是log4j,也能夠是Java Util Logging。app
與Commons Logging對立的陣營,這是接口,實現是Logback。框架
Slf4J的實現。工具
Slf4j實現機制決定Slf4j限制較少,使用範圍更廣。因爲Slf4j在編譯期間,靜態綁定本地的LOG庫使得通用性要比Commons logging要好。性能
Logback擁有更好的性能。Logback聲稱:某些關鍵操做,好比斷定是否記錄一條日誌語句的操做,其性能獲得了顯著的提升。這個操做在Logback中須要3納秒,而在Log4J中則須要30納秒。LogBack建立記錄器(logger)的速度也更快:13毫秒,而在Log4J中須要23毫秒。更重要的是,它獲取已存在的記錄器只需94納秒,而Log4J須要2234納秒,時間減小到了1/23。跟JUL相比的性能提升也是顯著的。
Commons Logging開銷更高 在使Commons Logging時爲了減小構建日誌信息的開銷,一般的作法是:
if(log.isDebugEnabled()){
log.debug("User name: " +
user.getName() + " buy goods id :" + good.getId());
}
複製代碼
在Slf4j陣營,你只需這麼作:
log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());
複製代碼
也就是說,slf4j把構建日誌的開銷放在了它確認須要顯示這條日誌以後,減小內存和cup的開銷,使用佔位符號,代碼也更爲簡潔。
jar包名 | 說明 |
---|---|
slf4j-log4j12-1.7.13.jar | log4j1.2版本的橋接器,你須要將log4j.jar加入classpath。 |
slf4j-jdk14-1.7.13.jar | java.util.logging的橋接器,JDK原生日誌框架。 |
slf4j-nop-1.7.13.jar | NOP橋接器,默默丟棄一切日誌。 |
slf4j-simple-1.7.13.jar | 一個簡單實現的橋接器,該實現輸出全部事件到System.err. 只有INFO以及高於該級別的消息被打印,在小型應用中它也許是有用的。 |
slf4j-jcl-1.7.13.jar | Jakarta Commons Logging 的橋接器. 這個橋接器將SLF4j全部日誌委派給JCL。 |
logback-classic-1.0.13.jar(requires logback-core-1.0.13.jar) | slf4j的原生實現,logback直接實現了slf4j的接口,所以使用slf4j與 logback的結合使用也意味更小的內存與計算開銷 |
具體接入方式以下:
在使用不一樣的框架的時候,可能別人集成的框架不同。好比Spring Framework集成的是Commons Logging,而XSocket依賴的是Java Util Logging。如今咱們須要解決不一樣框架中的不一樣日誌組件都統一爲Slf4J。SLF4J會根據綁定器把日誌交給具體的日誌實現工具。Slf4J帶有幾個橋接模塊,能夠重定向log4j,JCL和Java.util.logging中的api到Slf4J。
jar包名 | 做用 |
---|---|
log4j-over-slf4j-version.jar | 將log4j重定向到slf4j |
jcl-over-slf4j-version.jar | 將commons logging裏的Simple Logger重定向到slf4j |
jul-to-slf4j-version.jar | 將Java Util Logging 重定向到slf4j |
橋接方式參考下圖:
在使用slf4j橋接時要注意避免造成死循環,在項目依賴的jar包中不要存在如下狀況:
多個日誌jar包造成死循環的條件 | 產生緣由 |
---|---|
log4j-over-slf4j.jar和slf4j-log4j12.jar同時存在 | 因爲slf4j-log4j12.jar的存在會將全部日誌調用委託給log4j。但因爲同時因爲log4j-over-slf4j.jar的存在,會將全部對log4j api的調用委託給相應等值的slf4j,因此log4j-over-slf4j.jar和slf4j-log4j12.jar同時存在會造成死循環 |
jul-to-slf4j.jar和slf4j-jdk14.jar同時存在 | 因爲slf4j-jdk14.jar的存在會將全部日誌調用委託給jdk的log。但因爲同時jul-to-slf4j.jar的存在,會將全部對jul api的調用委託給相應等值的slf4j,因此jul-to-slf4j.jar和slf4j-jdk14.jar同時存在會造成死循環。 |