1. 程式人生 > 其它 >《手把手教你》系列基礎篇(八十七)-java+ selenium自動化測試-框架設計基礎-Log4j 2實現日誌輸出-上篇(詳解教程)

《手把手教你》系列基礎篇(八十七)-java+ selenium自動化測試-框架設計基礎-Log4j 2實現日誌輸出-上篇(詳解教程)

1.簡介

Apache Log4j 是一個非常古老的日誌框架,並且是多年來最受歡迎的日誌框架。 它引入了現代日誌框架仍在使用的基本概念,如分層日誌級別和記錄器。

2015 年 8 月 5 日,該專案管理委員會宣佈 Log4j 1.x 已達到使用壽命。 建議使用者使用 Log4j 1 升級到 Apache Log4j 2。因此巨集哥覺得有必要介紹一下Log4j 2,今天就單獨一篇介紹一下。

2.Log4j2簡介

Apache Log4j 2是對 Log4j 的升級,它比其前身 Log4j 1.x 提供了重大改進,並提供了 Logback 中可用的許多改進,同時修復了 Logback 架構中的一些固有問題。

與 Logback 一樣,Log4j2 提供對 SLF4J 的支援,自動重新載入日誌配置,並支援高階過濾選項。 除了這些功能外,它還允許基於 lambda 表示式對日誌語句進行延遲評估,為低延遲系統提供非同步記錄器,並提供無垃圾模式以避免由垃圾收集器操作引起的任何延遲。

所有這些功能使 Log4j2 成為這三個日誌框架中最先進和最快的。

3.log4j2優點

log4j2參考了logback的一些優秀的設計,並且修復了一些問題,因此帶來了一些重大的提升,主要有:

(1)異常處理:在logback中,Appender中的異常不會被應用感知到,但是在log4j2中,提供了一些異常處理機制。

(2)效能提升:log4j2相較於log4j 1和logback都具有很明顯的效能提升。

(3)自動過載配置:參考了logback的設計,提供自動重新整理引數配置,可以動態的修改日誌的級別而不需要重啟應用。

(4)無垃圾機制,log4j2在大部分情況下,都可以使用其設計的一套無垃圾機制,避免頻繁的日誌收集導致的jvm gc。

 4.log4j2配置說明

log4j 2.x版本不再支援像1.x中的.properties字尾的檔案配置方式,2.x版本常用.xml字尾的檔案進行配置,除此之外還包含.json和.jsn配置檔案

log4j2雖然採用xml風格進行配置,依然包含三個元件,分別是 Logger(記錄器)、Appender(輸出目的地)、Layout(日誌佈局)。

4.1XML配置檔案解析

(1)根節點Configuration有兩個屬性:status和monitorinterval,有兩個子節點:Appenders和Loggers(表明可以定義多個Appender和Logger).

status用來指定log4j本身的列印日誌的級別.monitorinterval為log4j 2.x新特點自動過載配置。指定自動重新配置的監測間隔時間,單位是s,最小是5s。

(2)Appenders節點,常見的有三種子節點:Console、File、RollingFile

Console節點用來定義輸出到控制檯的Appender.File節點用來定義輸出到指定位置的檔案的Appender.RollingFile節點用來定義超過指定大小自動刪除舊的建立新的的Appender.

通過在子節點中加入<PatternLayout pattern="自定義資訊格式"/>進行日誌佈局

%c 輸出所屬類的全名,可寫為 %c{Num} ,Num類名輸出的範圍 如:"com.sun.aaa.classB",%C{2}將使日誌輸出輸出範圍為:aaa.classB%d 輸出日誌時間其格式為 可指定格式 如 %d{HH:mm:ss}等%l 輸出日誌事件發生位置,包括類目名、發生執行緒,在程式碼中的行數%n 換行符%m 輸出程式碼指定資訊,如info(“message”),輸出message%p 輸出日誌的優先順序,即 FATAL ,ERROR 等%r 輸出從啟動到顯示該條日誌資訊所耗費的時間(毫秒數)%t 輸出產生該日誌事件的執行緒名

(3)Loggers節點,常見的有兩種:Root和Logger.

Root節點用來指定專案的根日誌,如果沒有單獨指定Logger,那麼就會預設使用該Root日誌輸出

Logger節點用來單獨指定日誌的形式,比如要為指定包下的class指定不同的日誌級別等。

5.日誌的級別

我們現在要呼叫logger的方法,不過在這個Logger物件中,有很多方法,所以要先了解log4j的日誌級別,log4j規定了預設的幾個級別:trace<debug<info<warn<error<fatal等。這裡要說明一下:

級別之間是包含的關係,意思是如果你設定日誌級別是trace,則大於等於這個級別的日誌都會輸出。

基本上預設的級別沒多大區別,就是一個預設的設定。你可以通過它的API自己定義級別。你也可以隨意呼叫這些方法,不過你要在配置檔案裡面好好處理了,否則就起不到日誌的作用了,而且也不易讀,相當於一個規範,你要完全定義一套也可以,不用沒多大必要。

這不同的級別的含義大家都很容易理解,這裡就簡單介紹一下:

trace:是追蹤,就是程式推進以下,你就可以寫個trace輸出,所以trace應該會特別多,不過沒關係,我們可以設定最低日誌級別不讓他輸出。

debug:除錯麼,我一般就只用這個作為最低級別,trace壓根不用。是在沒辦法就用eclipse或者idea的debug功能就好了麼。

info:輸出一下你感興趣的或者重要的資訊,這個用的最多了。

warn:有些資訊不是錯誤資訊,但是也要給程式設計師的一些提示,類似於eclipse中程式碼的驗證不是有error 和warn(不算錯誤但是也請注意,比如以下depressed的方法)。

error:錯誤資訊。用的也比較多。

fatal:級別比較高了。重大錯誤,這種級別你可以直接停止程式了,是不應該出現的錯誤麼!不用那麼緊張,其實就是一個程度的問題。

6.環境準備

6.1準備工作

1.下載地址:https://logging.apache.org/log4j/2.x/download.html 巨集哥可以通過下載地址下載最新版本是2.17.2。如下圖所示:

2.去官方下載log4j 2,匯入jar包,基本上你只需要匯入下面兩個jar包就可以了(xx是亂七八糟的版本號):

(1)log4j-core-xx.jar

(2)log4j-api-xx.jar

下載好了之後,將jar包新增到Eclipse專案的lib中去。如下圖所示:

 到此準備工作已經完成了,下邊巨集哥開始實戰!

7.專案實戰

7.1開始使用

我們知道,要在某個類中使用log4j記錄日誌,只需要申明下面的成員變數(其實不一定要是成員變數,只是為了方便呼叫而已)

private static Logger logger = LogManager.getLogger(MyApp.class.getName());

這裡getLogger有一個引數指定的是這個logger的名稱,這個名稱在配置檔案裡面可是有需要的,這個待會兒再說。

聲明瞭Logger物件,我們就可以在程式碼中使用他了。

7.2程式碼設計

1.在這裡巨集哥隨便寫個測試類,呼叫就是這麼簡單,log4j的核心在配置檔案上。如下圖所示:

2.如果沒有自定義配置檔案,上面這個類在寫一個main方法,呼叫測試類的方法。就可以執行程式碼測試你寫的測試類。如下圖所示:

7.3參考程式碼

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @author 北京-巨集哥
 * 
 * @公眾號:北京巨集哥
 * 
 * 《手把手教你》系列基礎篇(八十六)-java+ selenium自動化測試-框架設計基礎-Log4j 2實現日誌輸出(詳解教程)
 *
 * 2022年3月24日
 */

public class Test {
    
    static Logger logger = LogManager.getLogger(Test.class.getName());

    public boolean hello() {
        logger.entry(); // trace級別的資訊,單獨列出來是希望你在某個方法或者程式邏輯開始的時候呼叫,和logger.trace("entry")基本一個意思
        logger.error("Did it again!"); // error級別的資訊,引數就是你輸出的資訊
        logger.info("我是info資訊"); // info級別的資訊
        logger.debug("我是debug資訊");
        logger.warn("我是warn資訊");
        logger.fatal("我是fatal資訊");
        logger.log(Level.DEBUG, "我是debug資訊"); // 這個就是制定Level型別的呼叫:誰閒著沒事呼叫這個,也不一定哦!
        logger.exit(); // 和entry()對應的結束方法,和logger.trace("exit");一個意思
        return false;
    }
    public static void main(String[] args) {
        
        Test t = new  Test();
        t.hello();
    }
}

7.4執行程式碼

1.執行程式碼,右鍵Run AS->Java Appliance,控制檯輸出,如下圖所示:

從上圖可以看到,只有>=ERROR的日誌輸出來了(這是因為Log4j有一個預設的配置,它的日誌級別是ERROR,輸出只有控制檯)。

7.5定義日誌級別

1.巨集哥自己新建一個xml檔案放在SRC目錄下,即根目錄下。命令為log4j2.xml,定義好了日誌,把日誌級別改成了TRACE,如下圖所示:

 2.參考XML:

<?xml version="1.0" encoding="UTF-8"?>  
<configuration status="OFF">  
  <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="TRACE">  
      <appender-ref ref="Console"/>  
    </root>  
  </loggers>  
</configuration>  

3.再次執行程式碼,控制檯輸出如下圖所示:

 從上邊的xml檔案可以看到巨集哥把configuration>loggers>root的level屬性改為trace,就可以輸出剛才寫的所有資訊了。

 8.外部引用xml配置檔案

8.1程式碼設計

8.2參考程式碼

package testSuites;

import java.io.File;  
import java.io.FileInputStream;    
import org.apache.logging.log4j.LogManager;  
import org.apache.logging.log4j.Logger;  
import org.apache.logging.log4j.core.config.ConfigurationSource;  
import org.apache.logging.log4j.core.config.Configurator;  
  
/**
 * @author 北京-巨集哥
 * 
 * @公眾號:北京巨集哥
 * 
 * 《手把手教你》系列基礎篇(八十六)-java+ selenium自動化測試-框架設計基礎-Log4j2實現日誌輸出(詳解教程)
 *
 * 2022年3月27日
 */

public class ConfigTest {  
      
    private static Logger logger = LogManager.getLogger(ConfigTest.class);  
    /** 
     * log4j 2讀取配置檔案 
     * log4j 2讀取的配置檔案可以分為三類:src下的配置檔案、絕對路徑的配置檔案、相對路徑的配置檔案 
     */  
      
    //第一類  載入src下的配置檔案  
    public static void test0(){  
        //src下的配置檔案會預設的被log4j的框架載入,我們就不顯示的載入了  
        //直接測試  
        logger.info("我列印了.......");  
        //輸出內容  
        //11:06:16.957 [main] INFO  testSuites.ConfigTest - 我列印了.......
    }  
      
    //第二類  絕對路徑的配置檔案  
    public static void test1(){  
        //我們將log4j2.xml放在D盤下  
        //這是需要手動的載入  
        //絕對路徑配置檔案        
        ConfigurationSource source;  
        try {  
            //方法1  使用  public ConfigurationSource(InputStream stream) throws IOException 建構函式  
            source = new ConfigurationSource(new FileInputStream("F:\\workspace\\Bjhg_Selenium\\log4j2.xml"));  
              
            //方法2 使用 public ConfigurationSource(InputStream stream, File file)建構函式  
            File config=new File("F:\\workspace\\Bjhg_Selenium\\log4j2.xml");  
            source = new ConfigurationSource(new FileInputStream(config),config);  
              
            //方法3 使用 public ConfigurationSource(InputStream stream, URL url) 建構函式  
            String path="F:\\workspace\\Bjhg_Selenium\\log4j2.xml";  
            source = new ConfigurationSource(new FileInputStream(path),new File(path).toURL());  
              
            //source.setFile(new File("D:\log4j2.xml"));          
            //source.setInputStream(new FileInputStream("D:\log4j2.xml"));        
            Configurator.initialize(null, source);                
            Logger logger = LogManager.getLogger(ConfigTest.class.getName());         
            logger.trace("trace...");         
            logger.debug("debug...");         
            logger.info("info...");       
            logger.warn("warn...");       
            logger.error("error...");         
            logger.fatal("fatal...");  
            //一下是執行效果  
            /*11:57:38.457 [main] ERROR testSuites.ConfigTest - error...
              11:57:38.461 [main] FATAL testSuites.ConfigTest - fatal...*/  
        } catch (Exception e) {  
            e.printStackTrace();  
        }         
    }  
      
    //第三類  相對路徑的配置檔案載入  
    public static void test2(){  
        //這裡需要注意路徑中不要出現中文和空格,如果存在中文,請使用url轉碼  
        ConfigurationSource source;  
        try {  
            //方法1 使用System.getProperty  
            String config=System.getProperty("user.dir");  
            source = new ConfigurationSource(new FileInputStream(config+"/log4j2.xml"));  
            Configurator.initialize(null, source);  
            Logger logger = LogManager.getLogger(ConfigTest.class.getName());         
            logger.trace("trace...");         
            logger.debug("debug...");         
            logger.info("info...");       
            logger.warn("warn...");       
            logger.error("error...");         
            logger.fatal("fatal...");  
              
            //輸出內容  
            /*11:57:38.457 [main] ERROR testSuites.ConfigTest - error...
              11:57:38.461 [main] FATAL testSuites.ConfigTest - fatal...*/  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
      
    public static void main(String[] args) {  
        //test0();  
        //test1();  
        test2();  
    }  
}  

8.3執行程式碼

1.執行程式碼,右鍵Run AS->Java Appliance,控制檯輸出,如下圖所示:

9.小結

 好了,時間也不早了,今天就分享和講解到這裡,希望對您有所幫助,感謝您耐心地閱讀!