log4j到log4j2升級遷移方案


序:這段時間因為維護的項目存在大量日志打印,嚴重拖慢整體響應時間,在做性能優化的工作中對這塊內容進行了升級換代,由以前的log4j升級為log4j2,以實現日志異步打印。接下來記錄一下這個費時半個月的遷移踩過的坑!

相關操作步驟:

1. 在項目中移除log4j的依賴,並添加log4j2的相關依賴.(選擇log4j2的版本時請留意,2.10.x之后的版本是基於java9的!如果有使用到某些特性,請考慮當前項目的jdk版本!)

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
</dependency>

我最開始使用的2.11.2版本,因為jdk原因退回到2.9.1(請注意如果你的項目是通過jenkins構建,請將api,core包的依賴直接添加進來!)  

2.修改項目中所有的報錯!(這些都是jar包替換造成的!注意log4j2在實現方面與log4j是有區別的,常用的3個為:自定義appender自定義日志等級獲取logger的方式)

自定義appender方式:

@Plugin(
        name = "CustomerAppender",
        category = "Core",
        elementType = "appender",
        printObject = true
)

public final class CustomerAppender extends AbstractOutputStreamAppender<CustomerRollingFileManager> {


//TODO
//此部分為自定義內容    


}

  

3.本文以maven依賴管理為例,查看dependencies樹,確保項目中沒有其他依賴的依賴引入log4j相關jar包

這個步驟自行解決~~舉例如下:

   <dependency>
            <groupId>net.sourceforge.jexcelapi</groupId>
            <artifactId>jxl</artifactId>
            <version>2.6.12</version>
            <exclusions>
                <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

  

4.為步驟三中找到並移除的實現引入需要的橋接包!(此處注意大多數的項目中使用的 都是slf4j的框架,不同的版本使用Log4j2的實現需要的橋接包版本是不一樣的!請仔細查看相關版本)

<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>x.x.x</version>
        </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>x.x.x</version>
        </dependency>

  請根據實際需要修改對應版本,建議在maven repository中查詢版本對應關系

 

5.根據原有log4j.xml的配置文件改造log4j2.xml(原來通過java定義的日志等級可以遷移到此處)

<CustomLevels>
    <CustomLevel name="BUSI" intLevel="350" />
</CustomLevels>

  這里可以根據需要定義name,一級level,注意這個值與log4j定義的不太一樣,具體請參考源碼中的定義規則,我此處給的350在info等級以上

 

6.解決kafka日志推送問題.(log4j推送kafka一般是通過kafka-log4j-appender這個中間包去實現的,在lo4j2下需要更換推送方式,有內置的kafkaAppender,需要在依賴管理中根據需要推送的kafka服務端版本號添加對應的客戶端版本號:kafka-clients)

<!--kafka日志推送-->
        <Kafka name="kafkaAppender" topic="test" ignoreExceptions="true">
            <PatternLayout pattern="${Console_Pattern}" />
            <Property name="bootstrap.servers">x.x.x.x:端口號,x.x.x.x:端口號</Property>
            <Property name="max.block.ms">2000</Property>
        </Kafka>

  此處還可以設置ignoreException=false;這個時候需要去對異常做處理,可以獲取異常信息.

需要添加的kafka-clients依賴如下(請修改具體版本):

<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.10.0.0</version>
        </dependency>

 

7.解決容器問題!這個並非所有的容器都需要(至少tomcat不需要。。)目前我們服務器端使用的為jboss。在對日志升級后有可能出現對應業務日志打印到jboss的server日志中!這肯定是不允許的!解決辦法:在項目的WEB-INF或者META-INF目錄下添加:jboss-deployment-structure.xml文件,注意此處放置的位置和文件名都必須是這個!這是jboos規定的。此文件的作用是可以管理jboss的相關依賴,可以在此處排除它的log4j2的實包

<?xml version="1.0" encoding="UTF-8" ?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>

        <exclude-subsystems>
            <!-- 排除 javax.persistence.api 依賴 -->
            <subsystem name="jpa" />

            <!-- 排除 org.jboss.logging 依賴 -->
            <subsystem name="logging" />
        </exclude-subsystems>

        <exclusions>
            <!-- 排除 org.apache.httpcomponents 依賴 -->
            <module name="org.jboss.resteasy.resteasy-jaxrs" />

            <!-- 排除 javax.persistence.api 依賴 -->
            <module name="javaee.api" />
            <module name="javax.persistence.api" />
            <module name="org.hibernate" />
        </exclusions>

        <dependencies>

            <!-- 排除 org.apache.httpcomponents 依賴 -->
            <!-- <module name="org.apache.httpcomponents" export="true"/> -->

            <!-- 排除 org.jboss.logging 依賴 -->
            <!-- <module name="org.jboss.logging" export="true" /> --

            <!-- 排除掉jboss的 slf4j 和 log4j 實現,使用我們程序自己的包 -->
             <!--<module name="org.apache.log4j" export="true" />-->
             <!--<module name="org.slf4j" export="true" />-->
            <module name="org.apache.commons.logging" export="true" />
            <module name="org.jboss.logging.jul-to-slf4j-stub" export="true" />

        </dependencies>
    </deployment>
</jboss-deployment-structure>

  請根據項目實際需要做相關排除

8.解決因為包裝自定義的logger導致的日志記錄中不能正常記錄logger打印位置的問題。(這個問題對於直接使用原生logger的項目不會有)在log4j2的api包下我們會發現沒有提供可以傳遞FQCN的接口!所以此處我們需要直接引入core下的具體實現。在實現類中有log.logIfEnabled()方法,此方法允許傳入(FQCN,level,maker,message).

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

public abstract class AbstractABFrameLogger {

    /** 線程棧查找方法深度 */
    private final static int STACK_DEEP_SIZE = 2;


    /** log4j把傳遞進來的callerFQCN在堆棧中一一比較,相等后,再往上一層即認為是用戶的調用類 */
    final static String FQCN = AbstractABFrameLogger.class.getName();

    protected Logger log;


    /**
     *
     * @param name name
     */
    public AbstractABFrameLogger(String name) {
        this.log = (Logger) LogManager.getLogger(name);
    }



    /**
     * 基本debug基本,封裝打印信息
     * @param objLogInfo Object
     */
    public void debug(Object objLogInfo) {
        log.logIfEnabled(FQCN,Level.DEBUG,null,objLogInfo);
    }

}

  

完成上述步驟后,整個log4j的升級工作也就差不多做完啦~恭喜


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM