2021年8月9日 星期一

slf4j 搭 log4j2 並進行基本操作

利用 slf4j 搭配 log4j2 進行基本操作,主要展示輸出到 console 和輸出到檔案兩種方式


環境

Intellij IDEA 2021.1

提要

設定檔的檔名 log4j2 是一個預設值,log4j2 固定會讀這個檔名。

文中的以時間區分生成 log 檔跟以檔案大小生成 log 可以同時用。

本文


1.目錄結構如下




2.上 MVNRepository (https://mvnrepository.com/) 取得 slf4j + log4j2 的 dependency,並複製到 pom.xml 下 (記得要 reload maven project)


pom.xml

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.14.1</version>
    <scope>test</scope>
</dependency>


3.測試用的程式碼


App.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {

    private static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) throws InterruptedException {
        while (true){
            logger.trace("Trace message");
            logger.debug("Debug message");
            logger.info("Info message");
            logger.warn("Warn message");
            logger.error("error message");
            Thread.sleep(100);
        }
    }
}


4. 設定檔 log4j2.propertiest,主要呈現輸出到 console 和輸出到檔案兩種方式


log4j2.properties

# consolelala 這個是自取的名稱,用意在表示這些設定屬於同一個 appender
# type:這個 appender 的類型
# name:名稱自定,在指定 logger 要連結那些 appender 時會用到
# layout.type:指定輸出的方式,有 HTMLLayout、PatternLayout、SimpleLayout、TTCCLayout 四種
# layout.pattern:PatternLayout 用的 pattern
# filter.threshold.type:指定 filter 的類型
# filter.threshold.level:指定 filter 要輸出何種層級的 log(ex. error),預設應該是 error 層級,
#  設定應該會跟 filter 的類型有關

# 輸出到 console
appender.consolelala.type = Console
appender.consolelala.name = myconsoleappender
appender.consolelala.layout.type = PatternLayout
appender.consolelala.layout.pattern = [%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n
appender.consolelala.filter.threshold.type = ThresholdFilter
appender.consolelala.filter.threshold.level = trace
appender.consolelala.ImmediateFlush=true

# log 輸出到檔案,RollingFile 會依照時間或檔案大小來做 rollover
# type:RollingFile 輸出到檔案
# fileName:存放 log 的檔名
# append:重啟時是否要清空 log 檔案,還是附加在現有檔案
# policies.type:當 appender 的 type 不同時,會有不同的策略,也有不同的設定值要設定
# policies.time.type:TimeBasedTriggeringPolicy 表示用時間觸發生成 log 的方式
# policies.time.interval:當設定以(ex.日/時/分),來生成 log 時,interval 可以設定是要以 
#  n 日/n 時/n 分來生成 log
# policies.time.modulate:設定當在計算每隔 interval 生成 log 時,是要從 logger 開始的時間
#  後間隔 interval 生成 log 還是從 0 開始算 (ex.0點 or 0分)
# filePattern:RollingFile 會以時間或檔案大小來生成 log,所以比方說隔日,或是檔案超過指定的大小時,會
#  依照這個 filePattern 指定的檔名去生成 log,決定要依照每天或每小時或每分鐘去生成
#  當設定包含到小時或分鐘時,就會變成依小時或依分鐘生成 log
#  以日分(%d{yyyy-MM-dd})、以小時分(%d{yyyy-MM-dd-hh})、以分鐘分(%d{yyyy-MM-dd-hh-mm})
#  也可以設定 (%d{yyyy-MM-dd-hh-mm-ss}) 到秒,不過沒什麼意義
#  注意表示小時的hh有分小寫(12時制)大寫(24時制)
# filter.threshold.type:filter 的類型
# filter.threshold.level:表示只輸出 trace 及比 trace 更嚴重的層級的 log,這邊是第二道設定,從 
#  logger 那邊的 level 設定要大於這邊的設定才有意義
# (不嚴重) trace < debug < info < warn < error (嚴重)

# 輸出到 file (依時間生成 log)
appender.rollingdaylog.type = RollingFile
appender.rollingdaylog.name = daylog        
appender.rollingdaylog.fileName = E:/logtest/daily.log
appender.rollingdaylog.filePattern = E:/logtest/daily-%d{yyyy-MM-dd-HH-mm}.log
appender.rollingdaylog.layout.type = PatternLayout
appender.rollingdaylog.layout.pattern = [%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n
appender.rollingdaylog.append = false
appender.rollingdaylog.policies.type = Policies
appender.rollingdaylog.policies.time.type = TimeBasedTriggeringPolicy
appender.rollingdaylog.policies.time.interval = 3
appender.rollingdaylog.policies.time.modulate = true
appender.rollingdaylog.filter.threshold.type = ThresholdFilter
appender.rollingdaylog.filter.threshold.level = trace

# filePattern:這邊的有多設定一個「-%i」,當log檔大小大於預設要生成時,若檔名重複,這個 「-%i」是
#  一個流水號
# policies.size.type:SizeBasedTriggeringPolicy 表示採用 log 檔案大小做生成的依據
# policies.size.size:設定檔案大於此大小做生成(ex. 1KB, 1MB, ...)
# strategy.min:當 log 生成時 -%i 流水號的值,從 strategy.min 到 strategy.max
#  也就表示只會保留從 min 到 max 這個範圍的數量的 log。如果 filePattern 設定到分鐘,min=1,min=5
#  則每分鐘就最多 1 ~ 5 個 log 檔,較舊的會被蓋掉(會自動更名)
# strategy.max
# ImmediateFlush:表示不做緩衝,直接輸出到 log,較吃 i/o 效能,實際上吃多少視 log 生成速度

# 輸出到 file (依檔案大小生成 log)
appender.rolling2.type = RollingFile
appender.rolling2.name = errorLog
appender.rolling2.fileName = E:/logtest/error.log
appender.rolling2.filePattern = E:/logtest/errorlog-%d{yyyy-MM-dd-HH-mm-ss}-%i.log
appender.rolling2.layout.type = PatternLayout
appender.rolling2.layout.pattern = [%-5p] [%d{yyyy/MM/dd HH:mm:ss:SSS} %C-%M] : %m%n
appender.rolling2.append = true
appender.rolling2.policies.type = Policies
appender.rolling2.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling2.policies.size.size = 10KB
appender.rolling2.strategy.type = DefaultRolloverStrategy
appender.rolling2.strategy.min = 1
appender.rolling2.strategy.max = 5
appender.rolling2.ImmediateFlush = true
appender.rolling2.filter.threshold.type = ThresholdFilter
appender.rolling2.filter.threshold.level = error

# rootLogger:透過 LoggerFactory.getLogger 生成的 logger 在沒有父 logger 
#  的時候統一繼承 rootLogger 的設定值
# rootLogger.level:定義 rootLogger 要輸出什麼層級的 log
# rootLogger.appenderRef:定義 rootLogger 要接上那些 appender (consolelogdemo、filelogdemo 自己命名就好)

# rootLogger 生
rootLogger.level = trace
# 指定要輸出到 console
rootLogger.appenderRef.consolelogdemo.ref = STDOUT
# 指定要輸出到 file
rootLogger.appenderRef.filelogdemo.ref = daylog
# 指定要輸出到 file,且因為 errorLog 這個 appender 設定 filter 的關係,這個 appender 等於專門輸出 error
rootLogger.appenderRef.filelogdemo2.ref = errorLog


5. xml 版本的設定檔 (多補一個同時使用時間和大小分log的)


log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" name="Log4j2PropertiesConfig">
    <Appenders>
        <!--輸出到 console-->
        <Console name="myconsoleappender" ImmediateFlush="true">
            <PatternLayout pattern="[%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n" />
            <ThresholdFilter level="trace" />
        </Console>
        <RollingFile name="daylog" fileName="E:/logtest/daily.log"
                    filePattern="E:/logtest/daily-%d{yyyy-MM-dd-HH-mm}.log">
            <PatternLayout>
                <Pattern>[%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingFile>
        <!--每分鐘生成一個 log 檔 (輸出到檔案)-->
        <RollingFile name="errorlog" fileName="E:/logtest/error.log"
                    filePattern="E:/logtest/errorlog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <PatternLayout pattern="[%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n" />
            <ThresholdFilter level="error"/>
            <Policies>
                <SizeBasedTriggeringPolicy  size="10 KB"/>
            </Policies>
            <DefaultRolloverStrategy min="1" max="5"/>
        </RollingFile>
        <!--每分鐘或檔檔案大於 1mb 時生成 log 檔,每分鐘最多保留 5 個-->
        <RollingFile name="errorlog2" fileName="E:/logtest/error2.log"
                    filePattern="E:/logtest/errorlog2-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <PatternLayout pattern="[%d{yy-MMM-dd HH:mm:ss:SSS}] [%p] [%c{1}:%L] - %m%n" />
            <ThresholdFilter level="error"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy  size="1 MB"/>
            </Policies>
            <DefaultRolloverStrategy min="1" max="5"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="trace" includeLocation="false">
            <AppenderRef ref="myconsoleappender" />
            <AppenderRef ref="daylog"/>
            <AppenderRef ref="errorlog"/>
        </Root>
    </Loggers>
</Configuration>

沒有留言:

張貼留言