新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「Java極客技術(shù)」,作者鴨血粉絲 。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java極客技術(shù)公眾號(hào)。

一、摘要
不管是使用何種編程語(yǔ)言,何種框架,日志輸出幾乎無(wú)處不再,也是任何商業(yè)軟件中必不可少的一部分。
總結(jié)起來(lái),日志的用途大致可以歸納成以下三種:
問(wèn)題追蹤:通過(guò)日志不僅僅包括我們程序的一些bug,也可以在安裝配置時(shí),通過(guò)日志可以發(fā)現(xiàn)問(wèn)題。
狀態(tài)監(jiān)控:通過(guò)實(shí)時(shí)分析日志,可以監(jiān)控系統(tǒng)的運(yùn)行狀態(tài),做到早發(fā)現(xiàn)問(wèn)題、早處理問(wèn)題。
安全審計(jì):審計(jì)主要體現(xiàn)在安全上,通過(guò)對(duì)日志進(jìn)行分析,可以發(fā)現(xiàn)是否存在非授權(quán)的操作。
以 Java 編程語(yǔ)言為例,打印日志的方式有很多,例如通過(guò)System.out.print()方法將關(guān)鍵信息輸出到控制臺(tái),也可以通過(guò) JDK 自帶的日志Logger類輸出,雖然 JDK 從1.4開(kāi)始支持日志輸出,但是功能單一,無(wú)法更好的滿足商業(yè)要求,于是誕生了很多第三方日志庫(kù),像我們所熟悉的主流框架log4j、log4j2、logback等,提供的 API 功能都遠(yuǎn)勝 JDK 提供的Logger。
二、Log4j
2.1、介紹
Log4j 是一種非常流行的日志框架,由Ceki Gülcü首創(chuàng),之后將其開(kāi)源貢獻(xiàn)給 Apache 軟件基金會(huì)。
Log4j 有三個(gè)主要的組件:Loggers(記錄器),Appenders (輸出源)和Layouts(布局)。這里可簡(jiǎn)單理解為日志類別、日志要輸出的地方和日志以何種形式輸出。
綜合使用這三個(gè)組件可以輕松地記錄信息的類型和級(jí)別,并可以在運(yùn)行時(shí)控制日志輸出的樣式和位置。
Log4j 的架構(gòu)大致如下:
當(dāng)我們使用 Log4j 輸出一條日志時(shí),Log4j 自動(dòng)通過(guò)不同的Appender(輸出源)把同一條日志輸出到不同的目的地。例如:
- console:輸出到屏幕;
- file:輸出到文件;
- socket:通過(guò)網(wǎng)絡(luò)輸出到遠(yuǎn)程計(jì)算機(jī);
- jdbc:輸出到數(shù)據(jù)庫(kù)
在輸出日志的過(guò)程中,通過(guò)Filter來(lái)過(guò)濾哪些log需要被輸出,哪些log不需要被輸出。
在Loggers(記錄器)組件中,級(jí)別分五種:DEBUG、INFO、WARN、ERROR和FATAL。
這五個(gè)級(jí)別是有順序的,DEBUG < INFO < WARN < ERROR < FATAL,分別用來(lái)指定這條日志信息的重要程度,明白這一點(diǎn)很重要,Log4j有一個(gè)規(guī)則:只輸出級(jí)別不低于設(shè)定級(jí)別的日志信息。
假設(shè)Loggers級(jí)別設(shè)定為INFO,則INFO、WARN、ERROR和FATAL級(jí)別的日志信息都會(huì)輸出,而級(jí)別比INFO低的DEBUG則不會(huì)輸出。
最后,通過(guò)Layout來(lái)格式化日志信息,例如,自動(dòng)添加日期、時(shí)間、方法名稱等信息。
具體輸出樣式配置,可以參考如下內(nèi)容Log4j2 - Layouts布局介紹
2.2、項(xiàng)目應(yīng)用
以 Java 項(xiàng)目為例,在 Maven 的pom.xml中添加如下依賴!
2.2.1、添加 maven 依賴
org.slf4j slf4j-api 1.6.6 org.slf4j slf4j-log4j12 1.6.6 log4j log4j 1.2.17
2.2.2、創(chuàng)建log4j配置
在實(shí)際應(yīng)用中,要使Log4j在系統(tǒng)中運(yùn)行須事先設(shè)定配置文件。
配置文件實(shí)際上也就是對(duì)Logger、Appender及Layout進(jìn)行相應(yīng)設(shè)定。
Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是properties屬性文件,二選一。
創(chuàng)建一個(gè)log4j.xml或者log4j.properties,將其放入項(xiàng)目根目錄下。
1、XML格式
2、XML格式
- log4j.rootLogger=INFO,M,C,E
- log4j.additivity.monitorLogger=false
- # INFO級(jí)別文件輸出配置
- log4j.appender.M=org.apache.log4j.DailyRollingFileAppender
- log4j.appender.M.File=/logs/info.log
- log4j.appender.M.ImmediateFlush=false
- log4j.appender.M.BufferedIO=true
- log4j.appender.M.BufferSize=16384
- log4j.appender.M.Append=true
- log4j.appender.M.Threshold=INFO
- log4j.appender.M.DatePattern='.'yyyy-MM-dd
- log4j.appender.M.layout=org.apache.log4j.PatternLayout
- log4j.appender.M.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
- # ERROR級(jí)別文件輸出配置
- log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
- log4j.appender.E.File=/logs/error.log
- log4j.appender.E.ImmediateFlush=true
- log4j.appender.E.Append=true
- log4j.appender.E.Threshold=ERROR
- log4j.appender.E.DatePattern='.'yyyy-MM-dd
- log4j.appender.E.layout=org.apache.log4j.PatternLayout
- log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
- # 控制臺(tái)輸出配置
- log4j.appender.C=org.apache.log4j.ConsoleAppender
- log4j.appender.C.Threshold=INFO
- log4j.appender.C.layout=org.apache.log4j.PatternLayout
- log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n
2.2.3、log4j使用
在需要打印日志的類中,引入Logger類,在需要的地方打印即可!
- package org.example.log4j.service;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class LogPrintUtil {
- /**log靜態(tài)常量*/
- private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
- public static void main(String[] args){
- logger.info("info信息");
- logger.warn("warn信息");
- logger.error("error信息");
- }
- }
當(dāng)然你還可以這樣寫(xiě)
- if(logger.isInfoEnabled()) {
- logger.info("info信息");
- }
- if(logger.isWarnEnabled()) {
- logger.warn("warn信息");
- }
2.2.4、isInfoEnabled()有何作用呢?
簡(jiǎn)單來(lái)說(shuō),在某些場(chǎng)景下,用isInfoEnabled()方法判斷下是能提升性能的!
例如我們打印這段內(nèi)容logger.info("User:" + userId + appId),程序在打印這行代碼時(shí),先對(duì)內(nèi)容("User:" + userId + appId)進(jìn)行字符串拼接,然后再輸出。
如果當(dāng)前配置文件中日志輸出級(jí)別是info,是直接輸出的,當(dāng)日志輸出級(jí)別是error時(shí),logger.info()的內(nèi)容時(shí)不輸出的,但是我們卻進(jìn)行了字符串拼接,如果加上if(logger.isInfoEnabled())進(jìn)行一次判定,logger.info()就不會(huì)執(zhí)行,從而更好的提升性能,這個(gè)尤其是在高并發(fā)和復(fù)雜log打印情況下提升非常顯著。
另外,ERROR及其以上級(jí)別的log信息是一定會(huì)被輸出的,所以只有l(wèi)ogger.isDebugEnabled、logger.isInfoEnabled和logger.isWarnEnabled()方法,而沒(méi)有l(wèi)ogger.isErrorEnabled方法。
三、Log4j2
3.1、介紹
log4j2 是 log4j 1.x 的升級(jí)版,參考了 logback 的一些優(yōu)秀的設(shè)計(jì),并且修復(fù)了一些問(wèn)題,因此帶來(lái)了一些重大的提升,主要特點(diǎn)有:
- 異常處理:在logback中,Appender中的異常不會(huì)被應(yīng)用感知到,但是在log4j2中,提供了一些異常處理機(jī)制。
- 性能提升, log4j2相較于log4j 1和logback都具有很明顯的性能提升,后面會(huì)有官方測(cè)試的數(shù)據(jù)。
- 自動(dòng)重載配置:參考了logback的設(shè)計(jì),當(dāng)然會(huì)提供自動(dòng)刷新參數(shù)配置,最實(shí)用的就是我們?cè)谏a(chǎn)上可以動(dòng)態(tài)的修改日志的級(jí)別而不需要重啟應(yīng)用——那對(duì)監(jiān)控來(lái)說(shuō),是非常敏感的。
- 無(wú)垃圾機(jī)制:log4j2在大部分情況下,都可以使用其設(shè)計(jì)的一套無(wú)垃圾機(jī)制,避免頻繁的日志收集導(dǎo)致的jvm gc。
3.2、項(xiàng)目應(yīng)用
3.2.1、添加 maven 依賴
org.slf4j slf4j-api 1.7.13 org.slf4j jcl-over-slf4j 1.7.13 runtime org.apache.logging.log4j log4j-api 2.4.1 org.apache.logging.log4j log4j-core 2.4.1 org.apache.logging.log4j log4j-slf4j-impl 2.4.1 com.lmax disruptor 3.2.0
3.2.2、創(chuàng)建log4j2配置
在項(xiàng)目的根目錄下創(chuàng)建一個(gè)log4j2.xml的文件,與log4j相比,log4j2的異步輸出日志性能非常強(qiáng)勁,配置如下:
1、同步輸出日志
/logs/log4j2 /logs/log4j2/history
2、異步輸出日志
/logs/log4j2 /logs/log4j2/history
詳細(xì) API 可以參考官方網(wǎng)站!
3.2.3、log4j2使用
與 log4j 類似,直接在需要位置打印日志即可
- package org.example.log4j.service;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class LogPrintUtil {
- /**log靜態(tài)常量*/
- private static final Logger logger = LoggerFactory.getLogger(LogPrintUtil.class);
- public static void main(String[] args){
- logger.info("info信息");
- logger.warn("warn信息");
- logger.error("error信息");
- }
- }
四、Logback
4.1、介紹
Logback 也是用 java 編寫(xiě)一款非常熱門的日志開(kāi)源框架,由 log4j 創(chuàng)始人寫(xiě)的,性能比 log4j 要好!
logback 主要分為3個(gè)模塊:
- logback-core:核心代碼模塊
- logback-classic:log4j的一個(gè)改良版本,同時(shí)實(shí)現(xiàn)了slf4j的接口,這樣你如果之后要切換其他日志組件也是一件很容易的事
- logback-access:訪問(wèn)模塊與Servlet容器集成提供通過(guò)Http來(lái)訪問(wèn)日志的功能
4.2、項(xiàng)目應(yīng)用
4.2.1、添加 maven 依賴
ch.qos.logback logback-classic 1.2.3 org.codehaus.janino janino 2.7.8
4.2.2、創(chuàng)建logback配置文件
1、配置說(shuō)明
logback在啟動(dòng)的時(shí)候,會(huì)按照下面的順序加載配置文件:
- 如果java程序啟動(dòng)時(shí)指定了logback.configurationFile屬性,就用該屬性指定的配置文件。如java -Dlogback.configurationFile=/path/to/mylogback.xml Test,這樣執(zhí)行Test類的時(shí)候就會(huì)加載/path/to/mylogback.xml配置
- 在classpath中查找logback.groovy文件
- 在classpath中查找logback-test.xml文件
- 在classpath中查找logback.xml文件
- 如果是jdk6+,那么會(huì)調(diào)用ServiceLoader查找 com.qos.logback.classic.spi.Configurator接口的第一個(gè)實(shí)現(xiàn)類
- 自動(dòng)使用ch.qos.logback.classic.BasicConfigurator,在控制臺(tái)輸出日志
上面的順序表示優(yōu)先級(jí),使用java -D配置的優(yōu)先級(jí)最高,只要獲取到配置后就不會(huì)再執(zhí)行下面的流程。相關(guān)代碼可以看ContextInitializer#autoConfig()方法。
2、同步輸出日志
- value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{90} - %msg%n" />
${CONTEXT_NAME} ${CUSTOM_LOG_PATTERN} UTF-
當(dāng)前題目:Log配置教程及框架性能比較,看這篇就夠了!
網(wǎng)站路徑:http://fisionsoft.com.cn/article/cdssggp.html


咨詢
建站咨詢
