Log4j2配置文件詳解


目錄[-]

1 系列目錄

2 默認配置

本來以為Log4J2應該有一個默認的配置文件的,不過好像沒有找到(通過DefaultConfiguration,初始化一個最小化配置),下面這個配置文件等同於缺省配置:

    <?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="error"> <appender-ref ref="Console"/> </root> </loggers> </configuration> 

3 第一個配置例子

配置Log4j 2可以有四種方法(其中任何一種都可以):

  1. 通過一個格式為XML或JSON的配置文件。
  2. 以編程方式,通過創建一個ConfigurationFactory工廠和Configuration實現
  3. 以編程方式,通過調用api暴露在配置界面添加組件的默認配置。
  4. 以編程方式,通過調用Logger內部類上的方法。

注意,與Log4j 1.x不一樣的地方,公開的Log4j 2 API沒有提供任何添加、修改或刪除 appender和過濾器或者操作配置文件的方法。

Log4j能夠自動配置本身在初始化期間。當Log4j啟動它將定位所有的ConfigurationFactory插件和安排然后在加權從最高到最低。Log4j包含兩個ConfigurationFactory實現,一個用於JSON和XML。加載配置文件流程如下:

  1. Log4j將檢查“Log4j的配置文件“系統屬性,如果設置,將嘗試加載配置使用 ConfigurationFactory 匹配的文件擴展
  2. 如果沒有系統屬性設置JSON ConfigurationFactory log4j2-test將尋找。 json或 log4j2-test。json在類路徑中。
  3. 如果沒有這樣的文件發現XML ConfigurationFactory log4j2-test將尋找。 xml在 類路徑。
  4. 如果一個測試文件無法找到JSON ConfigurationFactory log4j2將尋找。 log4j2.jsn json或 在類路徑中。
  5. 如果一個JSON文件無法找到XML ConfigurationFactory將試圖定位 log4j2。 xml在類路徑中。
  6. 如果沒有配置文件可以找到了 DefaultConfiguration 將被使用。 這將導致日志輸出到控制台。
    <?xml version="1.0" encoding="UTF-8"?> <configuration status="OFF"> <appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </appenders> <loggers> <!--我們只讓這個logger輸出trace信息,其他的都是error級別--> <!-- additivity開啟的話,由於這個logger也是滿足root的,所以會被打印兩遍。 不過root logger 的level是error,為什么Bar 里面的trace信息也被打印兩遍呢 --> <logger name="cn.lsw.base.log4j2.Hello" level="trace" additivity="false"> <appender-ref ref="Console"/> </logger> <root level="error"> <appender-ref ref="Console"/> </root> </loggers> </configuration> 

我們這里看到了配置文件里面是name很重要,沒錯,這個name可不能隨便起(其實可以隨便起)。這個機制意思很簡單。就是類似於java package一樣,比如我們的一個包:cn.lsw.base.log4j2。而且,可以發現我們前面生成Logger對象的時候,命名都是通過 Hello.class.getName(); 這樣的方法,為什么要這樣呢? 很簡單,因為有所謂的Logger 繼承的問題。比如 如果你給cn.lsw.base定義了一個logger,那么他也適用於cn.lsw.base.lgo4j2這個logger。名稱的繼承是通過點(.)分隔的。然后你可以猜測上面loggers里面有一個子節點不是logger而是root,而且這個root沒有name屬性。這個root相當於根節點。你所有的logger都適用與這個logger,所以,即使你在很多類里面通過類名.class.getName() 得到很多的logger,而且沒有在配置文件的loggers下面做配置,他們也都能夠輸出,因為他們都繼承了root的log配置

我們上面的這個配置文件里面還定義了一個logger,他的名稱是 cn.lsw.base.log4j2.Hello ,這個名稱其實就是通過前面的Hello.class.getName(); 得到的,我們為了給他單獨做配置,這里就生成對於這個類的logger,上面的配置基本的意思是只有cn.lsw.base.log4j2.Hello 這個logger輸出trace信息,也就是他的日志級別是trace,其他的logger則繼承root的日志配置,日志級別是error,只能打印出ERROR及以上級別的日志。如果這里logger 的name屬性改成cn.lsw.base,則這個包下面的所有logger都會繼承這個log配置(這里的包是log4j的logger name的“包”的含義,不是java的包,你非要給Hello生成一個名稱為“myhello”的logger,他也就沒法繼承cn.lsw.base這個配置了。

那有人就要問了,他不是也應該繼承了root的配置了么,那么會不會輸出兩遍呢?我們在配置文件中給了解釋,如果你設置了additivity="false",就不會輸出兩遍

4 復雜一點的配置

    <?xml version="1.0" encoding="UTF-8"?> <!-- Configuration后面的status,這個用於設置log4j2自身內部的信息輸出,可以不設置,當設置成trace時,你會看到log4j2內部各種詳細輸出。 --> <!-- monitorInterval:Log4j能夠自動檢測修改配置 文件和重新配置本身,設置間隔秒數。 --> <configuration status="error" monitorInterval=”30″> <!--先定義所有的appender--> <appenders> <!--這個輸出控制台的配置--> <Console name="Console" target="SYSTEM_OUT"> <!--控制台只輸出level及以上級別的信息(onMatch),其他的直接拒絕(onMismatch)--> <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> <!--這個都知道是輸出日志的格式--> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </Console> <!--文件會打印出所有信息,這個log每次運行程序會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用--> <File name="log" fileName="log/test.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <!-- 這個會打印出所有的信息,每次大小超過size,則這size大小的日志會自動存入按年份-月份建立的文件夾下面並進行壓縮,作為存檔--> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> <SizeBasedTriggeringPolicy size="50MB"/> <!-- DefaultRolloverStrategy屬性如不設置,則默認為最多同一文件夾下7個文件,這里設置了20 --> <DefaultRolloverStrategy max="20"/> </RollingFile> </appenders> <!--然后定義logger,只有定義了logger並引入的appender,appender才會生效--> <loggers> <!--建立一個默認的root的logger--> <root level="trace"> <appender-ref ref="RollingFile"/> <appender-ref ref="Console"/> </root> </loggers> </configuration> 
  • 擴展組件

    1. ConsoleAppender:輸出結果到System.out或是System.err。
    2. FileAppender:輸出結果到指定文件,同時可以指定輸出數據的格式。append=“false”指定不追加到文件末尾
    3. RollingFileAppender:自動追加日志信息到文件中,直至文件達到預定的大小,然后自動重新生成另外一個文件來記錄之后的日志。
  • 過濾標簽

    1. ThresholdFilter:用來過濾指定優先級的事件。
    2. TimeFilter:設置start和end,來指定接收日志信息的時間區間。

4.1 Appender之Syslog配置

log4j2中對syslog的簡單配置,這里就不重復展示log4j2.xml了:

<Syslog name="SYSLOG" host="localhost" port="514" protocol="UDP" facility="LOCAL3"/> 

host是指你將要把日志寫到的目標機器,可以是ip(本地ip或遠程ip,遠程ip在實際項目中很常見,有專門的日志服務器來存儲日志),也可以使用主機名,如果是本地,還可以使用localhost或127.0.0.1。

Port指定端口,默認514,參見/etc/rsyslog.conf(以Fedora系統為例,下同)。protocol指定傳輸協議,這里是UDP,facility是可選項,后面可以看到用法。

4.2 Syslog及Syslog-ng相關配置(Fedora)

在運行程序之前,需要修改:/etc/rsyslog.conf

把這兩行前的#去掉,即取消注釋:

#$ModLoad imudp #$UDPServerRun 514 

這里啟用udp監聽,514是默認監聽端口,重啟syslog:

service syslog restart 

大部分日志會默認寫到/var/log/messages中,如果不想寫到這個文件里,可以按下面修改,這樣local3的日志就會寫到app.log中。這里的local3即 log4j2.xml中facility的配置。

*.info;mail.none;authpriv.none;cron.none;local3.none /var/log/messages 

新增一行:

local3.*                                                            /var/log/app.log 

除了使用自帶的syslog,我們也可以使用syslog的替代品,比如syslog-ng,這對於log4j2.xml配置沒有影響。 安裝:

yum install syslog-ng 

啟動:

service syslog-ng start 

其配置文件為:

/etc/syslog-ng/syslog-ng.conf 

啟動前把source一節中這一行取消注釋即可:

#udp(ip(0.0.0.0) port(514)); 

這個端口會和syslog沖突,可以使用別的端口比如50014,同時修改log4j2.xml中的port屬性。另外提一下,使用非默認端口,要求log4j版本在1.2.15或以上。

syslog-ng本身也可以設置把日志送到遠程機器上,在源機器上的syslog-ng.conf中添加:

destination d_remote1 {udp(153.65.171.73 port(514));}; 

這表示源機器上的syslog-ng會把接收到的日志送到遠程主機153.65.171.73的514端口上,只要保證153.65.171.73上的syslog-ng正常運行並監聽對應的端口即可。

5 Log4j2與Spring集成

web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- 讀取classpath 以 applicationContext 開頭的文件作為spring 的配置文件 -->
        <param-value>classpath*:applicationContext-*.xml</param-value>
    </context-param>
    <!-- 解決中文亂碼問題,將參數編碼為utf-8 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>


    <!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
    <!-- requests.  Usually this filter mapping is defined first (before all others) to -->
    <!-- ensure that Shiro works in subsequent filters in the filter chain:       -->

    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <!-- log4j2-begin for servlet 2.5
      <listener>
            <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
        </listener>
        <filter>
            <filter-name>log4jServletFilter</filter-name>
            <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>log4jServletFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>INCLUDE</dispatcher>
            <dispatcher>ERROR</dispatcher>
        </filter-mapping>
         log4j2-end -->

    <!-- log4j2-begin for servlet version >3.0-->
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/classes/log4j2.xml</param-value>
    </context-param>


    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <display-name>IotSupport</display-name>

</web-app>

 

轉自http://my.oschina.net/xianggao/blog/523401#OSC_h2_5


免責聲明!

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



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