1. 程式人生 > >Java for Web學習筆記(五十):Log(2)配置log4j2

Java for Web學習筆記(五十):Log(2)配置log4j2

相關maven

<!-- log4j-api提供logging的API。這是log4j2中唯一需要在compile時加入,含有你所需的所有類 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.8.1</version>
    <scope>compile</scope>
</dependency>  

<!-- log4j-core含有Log4j 2的實現,根據配置具體實現,而API不需要配置,也選擇在執行時。不過配置為compile似乎也沒什麼問題 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.8.1</version>
    <scope>runtime</scope>
</dependency>  

<!-- log4j-jcl是支援API的adapter。有lib採用Commons Logging API(Log4j),這個adapter可將Log4j 2作為它的實現。 -->
<!-- 如果我們想看到這些第三方庫的log,我們可以採用這種方式,例如httpclient,採用了commons-logging(具體參見 https://hc.apache.org/httpcomponents-client-4.3.x/httpclient-cache/dependencies.html ),通過加入log4j-jcl可以將log通過log4j2,也就是我們自己專案的log來輸出。 -->
<!-- 這個怎麼看了,有時也挺煩的。httpclient可以在debug情況下看出互動的包內容。 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-jcl</artifactId>
    <version>2.8.1</version>
    <scope>runtime</scope>
</dependency>

<!-- log4j-slf4j-impl是SLF4J的adapter,例如C3P0,如果開到DEBUG級別,那log就是眼花繚亂了。 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.8.1</version>
    <scope>runtime</scope>
</dependency>

<!-- log4j-taglib是JSP Tag lib的adapter。和之前一樣採用runtime,避免在編譯時出現不相容。 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-taglib</artifactId>
    <version>2.8.1</version>
    <scope>runtime</scope>
</dependency>

配置檔案位置

預設位置

  預設是在console中顯示error級別。配置檔案依次尋找為

  1. log4j.configurationFile
  2. log4j2-test.json 或 log4j2-test.jsn
  3. log4j2-test.xml
  4. log4j2.json 或 log4j2.jsn
  5. log4j2.xml
  6. 可以在程式碼中指定位置

  開發中預設位置如下,war包將存放在classpath中。

程式碼指定配置檔案

private static Logger logger = null;
/**
 * 指定log4j2的配置檔案
 * 參考:http://logging.apache.org/log4j/2.x/log4j-core/apidocs/index.html
 * 
 * @param file  配置檔名字,建議絕對路徑的方式
 * @throws FileNotFoundException 異常
 * @throws IOException 異常
 */
public static void initLogger(String file) throws FileNotFoundException,IOException{
    ConfigurationSource source = new ConfigurationSource(new FileInputStream(file),new File(file));
    Configurator.initialize(null, source);
    //【注意】必須要初始化之後,才設定logger的值,否則會出錯。          
    logger = LogManager.getLogger(); 
}

web.xml指定配置檔案

<context-param>
    <param-name>log4jConfiguration</param-name> 
    <param-value>D:\develop\eclipse-jee-mars-2-win32\book\customer-support\conf\log4j2.xml</param-value>
</context-param>

編寫配置檔案

一個簡單的配置檔案

  我們先從一個極為簡單的配置檔案開始
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration status的級別指的是log4j2自己本身的log,一般WARN就足以。
 monitorInterval強烈要求加上,本例表示每5分鐘(300秒)重新讀取配置檔案,我們可以準實時地修改log的級別。 -->
<configuration status="WARN" monitorInterval="300"> 
    <!-- appenders中定義log的目的地,本例第一個了名字為Console的appender,為SYSTEM_OUT方式輸出到Console -->
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </appenders>

    <!-- 程式碼中通過getLogger()獲得的logger例項。本例只定義了根looger,採用名字叫做Console的appender,級別為debug -->
    <loggers>
        <root level="debug">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

appender

  在appenders中可以定義多個appender,在實際應用中,我們希望將log記錄在檔案中,以便事後調閱,相關的appender如下:
<configuration ... ...>
    <!-- 為了方便修改,通常將log目錄和log名字定義為一個引數 -->
    <properties>
        <property name="logPath">/usr/local/log</property>
        <property name="logName">mytest</property>
    </properties>

    <appenders>
        ... 其他 appender ...
       <!-- log檔名字為mytest.log,當達到policy的條件時,將壓縮為zip檔案,並重新寫mytest.log。
            壓縮檔名字樣式在filepattern中定義,本例例子mytest-20170418-1.log.zip,%d{yyyyMMdd}表示以年月日,%i表示序號。%i的最大值在DefaultRolloverStrategy中定義,如果已經達到最大值,則刪除-1,將-2改名為-1,如此類推。 -->
       <RollingFile name="RollingFile" filename="${logPath}/${logName}.log"  filepattern="${logPath}/${logName}-%d{yyyyMMdd}-%i.log.zip">
           <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%-5level] - %msg%n"/> 
           <Policies>
               <!-- 當log檔案達到25M的時候,需要進行壓縮,新起一個log -->
               <SizeBasedTriggeringPolicy size="25 MB"/>
               <!-- 當新的1天(根據yyyyMMdd的最小時間間隔確定),需要進行壓縮,新起一個log -->
               <TimeBasedTriggeringPolicy interval="1" modulate="true" />
           </Policies>    
           <DefaultRolloverStrategy max="20"/>
       </RollingFile>    
    </appenders>

    <loggers>
         ......
    </loggers>
</configuration>

PatternLayout的pattern

  這裡定義輸出log的樣式

說明 樣式 例子
%d 時間戳
  •  %d{HH:mm:ss.SSS}
  •  %d{yyyy-MM-dd HH:mm:ss.SSS}
  •  %d{DEFAULT}
  •  %d{ISO8601}
  •  %d{UNIX}
  •  %d{UNIX_MILLIS}
  • 16:20:22.257
  • 2017-04-18 16:20:22.257
  • 2017-04-18 16:20:22,257
  • 2017-04-18T16:20:22,257
  • 1492503622
  • 1492503622257
%t 執行緒名字 [%t] [localhost-startStop-1]

我們可以利用執行緒名字,將請求和響應對應起來

%logger,%c:類名
  •  %c
  •  %c{2}
  •  %c{1}
  •  %c{2.}
  •  %c{1.}
  • cn.wei.flowingflying.chapter10.tictactoe.GlobalListener 全部資訊
  • tictactoe.GlobalListener 顯示最後2個
  • GlobalListener 顯示最後1個
  • cn.we.fl.ch.ti.GlobalListener 縮寫2個字母
  • c.w.f.c.t.GlobalListener 縮寫1個字母
 %l cn.wei.flowingflying.chapter10.tictactoe.GlobalListener.contextInitialized(GlobalListener.java:58)
方法名 %M contextInitialized
檔名字 %F GlobalListener.java
所在的行號 %L 58
訊息 %m %msg %message
換行 %n
日誌級別 %level
 %X  %X{id}

%X{username}

顯示ThreadContext中map裡面的資訊,在後面詳細說明

Loggers

  在loggers中定義一個或多個logger,程式碼中的logger例項將匹配其中某個。
<?xml version="1.0" encoding="UTF-8"?>
<configuration ... ...>
    ...... 

    <!-- 為了方便修改,通常將log目錄和log名字定義為一個引數 -->
    <loggers>
        <!-- root為最基本的根logger,匹配所有的logger例項。-->
        <root level="warn">
            <appender-ref ref="Console" />
        </root>

        <!-- 如果logger例項的字首cn.wei,則匹配此項。如果additivity為true,則最優匹配,不再往下匹配,即不在匹配root;如果為flase,則繼續匹配,本例還匹配root,相當還要在Console中輸出,級別為INFO,由本logger確定。-->
        <logger name="cn.wei" level="info" additivity="false">
            <appender-ref ref="WroxFileAppender" />
                <MarkerFilter marker="WROX_CONSOLE" onMatch="NEUTRAL" onMismatch="DENY" />
            </appender-ref>
        </logger>

        <!-- 匹配名字字首為org.apache的例項。預設additivity為true,即會在console中顯示 -->
        <logger name="org.apache" level="info">
            <appender-ref ref="WroxFileAppender" />
        </logger>
    </loggers>
</configuration>

Filter

  在前面已經提供了fiter的例子
<!-- NETUTAL表示繼續匹配,直到DENY或者ACCEPT,最後的預設為ACCEPT,本例maker為WROX_CONSOLE的log要ACCEPT,利用filter可以進行log的過濾 -->
<logger name="cn.wei" level="info" additivity="false">
     <appender-ref ref="WroxFileAppender" />
         <MarkerFilter marker="WROX_CONSOLE" onMatch="NEUTRAL" onMismatch="DENY" />
     </appender-ref>
</logger>

  除了在logger外,在Appender也可以定義filter,在configuration下面可以定義context-wide的filter。