天天看點

log4j2研究之配置檔案子產品化

子產品化作為軟體開發領域裡的重要思想之一,我們在實際的工作中處處都能看到其身影。本文将嘗試将這種思路應用到log4j2的配置檔案中。

1. 概述

在軟體開發領域,日志總是非常基礎且重要的一環。log4j2作為Java領域裡日志架構的佼佼者,後發優勢使其迅速獲得衆多開發者的青睐。

XML配置作為log4j2官方的首推配置方式,被絕大多數開發人員所熟知。但XML語言天然的繁瑣啰嗦的文法格式,以及具體業務場景下對日志的精密劃分,勢必導緻我們的log4j2.xml 這個配置檔案變得非常臃腫、龐大;于是一個改良思路順理成章地出現了:我們是否可以将這個檔案拆分成多個配置檔案,最後再将這些配置檔案組裝成為一個完整的配置?答案當然是肯定的,接下來筆者就介紹實作這種想法的兩種思路。

2. XInclude實作

這種實作方式其實和log4j2本身沒有太大的關系,這個屬于XML自帶的一種子產品化思路,具體的可以參見筆者在下面給出的連結。這裡就不作過多的糾結,具體的實作方式在官方文檔裡也已經給出了,讀者可以自行查閱(相應的官方文檔位址筆者在下面也已給出)。

這裡還是給出一些筆者在實際運用過程中遇到的一些注意事項:

  1. <xi:include />

    節點的放置位置很重要。對于include節點導入的内容, 有先後順序之别。
  2. 如果

    <properties>

    想要覆寫 log4j2-xinclude-properties.xml 中定義的屬性, 則需要保證

    <properties>

    在先,而在後。
  3. log4j2-xinclude-appenders.xml 中如果用到了 log4j2-xinclude-properties.xml 中配置的屬性,則必須 log4j2-xinclude-properties.xml 在先。
  4. 節點之間的覆寫是整體覆寫,例如下面樣例中的

    <properties>

    , 屬于

    <properties>

    節點覆寫,而不是裡面單個

    <property>

    的重複覆寫。而且xinclude檔案中定義時,必須是頂級節點(即Appenders/Loggers/Properties等。)
  5. 之前所談到的覆寫都是 先到者優先,即保留排名在前的配置項。
  6. 樣例XML如下:
    <!--主體log4j2.xml配置檔案-->
    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="error" xmlns:xi="http://www.w3.org/2001/XInclude">
        <!-- this will override the log pattern defined in the included log4j-properties.xml -->
        <!--這裡定義的Properties将覆寫log4j2-xinclude-properties.xml定義的内容, 注意是全部覆寫, 不僅僅是log-pattern屬性. 即使log4j2-xinclude-properties.xml中的Properties也許擁有更多的配置項。-->
        <Properties>
            <Property name="log-pattern">jit %d %-5p [%t] %C{1.} - %m%n</Property>
        </Properties>
    
        <xi:include href="log4j2-xinclude-properties.xml" />
        <xi:include href="log4j2-xinclude-appenders.xml" />
    </Configuration>
    
    <!-- log4j2-xinclude-properties.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <Properties>
        <!-- define the log pattern as a property so that it can be overridden -->
        <Property name="log-pattern">%d %-5p [%t] %C{1.} - %m%n</Property>
    </Properties>
               

注意:

  • 這種方式之下,應用所部署的路徑中不能包含有中文。

3. Composite Configuration實作

筆者在查找上一種解決方案的過程中,偶然在官網上看到了另外一種實作思路,也就是LOG4J2中論述的

Composite Configuration

(這裡也可以看出LOG4J2的後發優勢真是相當巨大,開發人員吸取了大量之前LOG架構的教訓并将之在log4j2中進行了解決)。

官方文檔裡并沒有給出相應的示例,筆者結合官方給出的文檔,再經過一番源碼追蹤後,大緻實作了一個可運作的版本。

  1. 首先你需要配置一個名為

    log4j.configurationFile

    的配置項(關于這個配置項,你可以在

    ConfigurationFactory

    類中找到),該配置項将指定log4j2的配置檔案所在位置。注意這個配置項是可以指定多個配置檔案的,你需要做的隻是使用逗号将它們分開(注意這個逗号目前是寫死在代碼裡的,具體位置是

    ConfigurationFactory.Factory

    類的

    getConfiguration(LoggerContext, String, URI)

    方法中)。
  2. 第一步提到的配置項,你需要将其放到classpath下建立的

    log4j2.component.properties

    檔案中(該檔案名是在

    PropertiesUtil

    類中定義的)。
  3. 第二步有一個替換操作,就是将

    log4j.configurationFile

    的配置項注冊到系統屬性中。
  4. 以上三步的邏輯主要涉及到

    ConfigurationFactory.Factory.getConfiguration()

    PropertiesUtil.getProperties().getStringProperty()

    。讀者可自行閱讀相應的源碼來做到成竹于胸。
  5. 最後給出一個配置示例:
    # 定義在classpath下的 log4j2.component.properties 檔案
    log4j.configurationFile=log4j2-test.xml,log4j2-test2.xml
               
  6. 關于配置之間的屬性覆寫問題以及其他實作細節,可以參見官方文檔說明,筆者就不重複了。

注意:

  • 這種方式之下,每個配置檔案必須滿足log4j2.xml的格式,例如XML情況下要以

    <Configuration>

    為根節點。

4. Links

  1. XML Inclusions (XInclude)
  2. StackOverflow - log4j2 - include
  3. log4j2-XInlcude官方文檔
  4. 自定義Log4j2配置檔案位置

繼續閱讀