日誌組件二:log4j2

1、背景

  隨着業務服務(Server App)逐漸增長,咱們的業務系統中的日誌輸出面臨的問題愈來愈多,高併發下對磁盤io這塊消耗的愈來愈大,所以,急須要一個高性能且最好可以支持異步輸出日誌的日誌框架,並且能兼容市面上目前主流的日誌組件(log4j1.x,logback等)java

2、簡介

  log4j2也是一款日誌組件,log4j1.x升級版本,而且log4j2和log4j是同一個做者,可是log4j2是從新架構的。在個人理解中,儘管log4j2相較於log4j有不少優勢,可是我採用它放棄log4j最大的理由是:它支持異步輸出,性能秒殺一切的日誌組件。web

log4j2的配置文件支持xml格式

<?xml version="1.0" encoding="UTF-8"?>
<!-- status=debug 能夠查看log4j的裝配過程 --> <Configuration status="INFO"> <properties> <!--變量定義 --> <Property name="baseDir">/data/logs/</Property> <property name="log_pattern">%-d{yyyy-MM-dd HH:mm:ss.SSS} [%t:%r] [%F:%L] - [%p] %m%n</property> <property name="file_name">info.log</property> <property name="error_file_name">error.log</property> <property name="warn_file_name">warn.log</property> <property name="rolling_file_name">wdmsg-%d{yyyy-MM-dd-HH}.log.%i</property> <!-- 日誌切割的最小單位 --> <property name="every_file_size">100M</property> </properties> <Appenders> <!--輸出控制檯的配置 --> <Console name="console" target="SYSTEM_OUT"> <!--控制檯只輸出level及以上級別的信息(onMatch),其餘的直接拒絕(onMismatch) --> <ThresholdFilter level="INFO" onMatch="ACCEPT" /> <!--輸出日誌的格式 --> <PatternLayout pattern="${log_pattern}" /> </Console> <!-- 輸出不一樣級別的日誌到不一樣的文件下 --> <RollingFile name="infoFile" fileName="${baseDir}${file_name}" filePattern="${baseDir}${rolling_file_name}"> <PatternLayout pattern="${log_pattern}" /> <Filters> <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL" /> <ThresholdFilter level="INFO" onMatch="ACCEPT" /> </Filters> <SizeBasedTriggeringPolicy size="${every_file_size}" /> </RollingFile> <RollingFile name="warnFile" fileName="${baseDir}${warn_file_name}" filePattern="${baseDir}${rolling_file_name}"> <PatternLayout pattern="${log_pattern}" /> <Filters> <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL" /> <ThresholdFilter level="WARN" onMatch="ACCEPT" /> </Filters> <SizeBasedTriggeringPolicy size="${every_file_size}" /> </RollingFile> <RollingFile name="errorFile" fileName="${baseDir}${error_file_name}" filePattern="${baseDir}${rolling_file_name}"> <PatternLayout pattern="${log_pattern}" /> <ThresholdFilter level="ERROR" onMatch="ACCEPT" /> <SizeBasedTriggeringPolicy size="${every_file_size}" /> </RollingFile> </Appenders> <Loggers> <!--創建一個默認的root的logger,須要在root的level中指定輸出的級別, --> <Root level="all"> <appender-ref ref="console" /> <appender-ref ref="infoFile" /> <appender-ref ref="warnFile" /> <appender-ref ref="errorFile" /> </Root> </Loggers> </Configuration>

一、根節點Configuration:有兩個屬性status和monitorintervalspring

status:用來指定log4j自己的打印日誌級別apache

monitorinterval:指定log4j自動從新配置的監測間隔時間api

二、Appenders節點:有三個子節點,Console、RollingFile、File架構

  Console:定義輸出到控制檯的Appender併發

  RollingFile:用來定義超過指定大小自動刪除舊的建立新的的Appendermvc

  File:輸出到指定位置的文件的Appenderapp

三、Loggers節點:經常使用的兩個子節點,Root、Logger框架

  Root:用來指定項目的根日誌,若是沒有單獨指定Logger,那麼就會默認使用該Root日誌輸出

  我本身試驗的結果以下:

2017-05-24 17:16:51,087 main WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender
五月 24, 2017 5:16:51 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [META-INF/spring/springContext.xml]
五月 24, 2017 5:16:51 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@465e1377: startup date [Wed May 24 17:16:51 CST 2017]; root of context hierarchy
17:16:51.360 [main] ERROR com.cd.mvc.controller.TestLog4j2 - error message

  這裏最後一行是用Root格式打印的日誌

  Logger單獨指定日誌的形式,如要爲jar包下的class指定不一樣的日誌級別。

  AppenderRef用來指定該日誌輸出到哪一個Appender,若是沒有指定,就會默認繼承自Root.若是指定了,那麼會在指定的這個Appender和Root的Appender中都會輸出,此時咱們能夠設置Logger的                                  additivity="false"只在自定義的Appender中進行輸出。

四、Filters

配置文件中有這麼一段,咱們來詳細解讀下,這個很是重要,涉及到不一樣級別的日誌輸出到對應的日誌文件中:

1  <Filters>
2     <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL" />
3     <ThresholdFilter level="INFO" onMatch="ACCEPT" />
4  </Filters>

ThresholdFilter有三個參數:

  level:將被過濾的日誌級別

  onMatch:默認值爲NEUTRAL

  onMismatch:默認是DENY

若是類中的日誌是warn級別,則匹配第一個過濾器,被直接DENY(拒絕),不被記錄到文件中
若是類中的日誌是info級別,則不匹配第一個過濾器,因爲採用的是中立的策略,會接着走到第二個過濾器,因爲匹配第二個,且被accept,則該日誌記錄到info日誌文件中。這樣就實現的前面提到的不一樣級別日誌輸出到對應的日誌文件中。

 3、log4j2的加載

  Log4j能夠在初始化的時候執行自動配置。當Log4j啓動的時候,首先會定位全部的ConfigurationFactory的配置,根據優先級順序進行加載;Log4j包含了四種類型的ConfigurationFactory的實現,JSONYAMLpropertiesXML。log4j2查找配置文件的順序:

4、SpringMVC集成log4j2

一、pom.xml

    <!--log4j2-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.4.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.0.2</version>
    </dependency>    

跟log4j2相關的只須要這兩個jar包

a、使用默認的配置文件

一、工程目錄

這個工程中,classpath下沒有log4j2.xml的配置文件,web.xml中我也沒有作任何log4j2相關的配置,這裏有意讓log4j讀取默認的配置

二、Junit測試類:

 1 package com.cd.mvc.controller;
 2 
 3 
 4 
 5 import org.apache.logging.log4j.LogManager;
 6 import org.apache.logging.log4j.Logger;
 7 import org.junit.Test;
 8 import org.junit.runner.RunWith;
 9 import org.springframework.test.context.ContextConfiguration;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 
12 
13 @RunWith(SpringJUnit4ClassRunner.class)
14 @ContextConfiguration("classpath:META-INF/spring/springContext.xml")
15 public class TestLog4j2
16 {
17     static Logger logger = LogManager.getLogger(TestLog4j2.class.getName());
18     
19     @Test
20     public void test()
21     {
22         logger.info("info message");
23         logger.warn("warn message");
24         logger.error("error message");
25     }
26 }

三、執行結果:

五月 24, 2017 7:11:27 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getDefaultTestExecutionListenerClassNames
INFO: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
五月 24, 2017 7:11:27 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
五月 24, 2017 7:11:27 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
五月 24, 2017 7:11:27 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getTestExecutionListeners
INFO: Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@1ed73856, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@43b3a5eb, org.springframework.test.context.support.DirtiesContextTestExecutionListener@47520a06]
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
五月 24, 2017 7:11:27 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [META-INF/spring/springContext.xml]
五月 24, 2017 7:11:27 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@115fae6: startup date [Wed May 24 19:11:27 CST 2017]; root of context hierarchy
19:11:28.065 [main] ERROR com.cd.mvc.controller.TestLog4j2 - error message

最後一行就是採用log4j默認的配置打印出來的日誌,咱們來看下具體的默認配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2  <Configuration status="WARN">
 3      <Appenders>
 4           <Console name="Console" target="SYSTEM_OUT">
 5               <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
 6           </Console>
 7       </Appenders>
 8       <Loggers>
 9           <Root level="error">
10              <AppenderRef ref="Console" />
11          </Root>
12      </Loggers>
13  </Configuration>

這裏只配置了一個Console的Appender,級別是error,因此咱們在控制檯上看到了這種格式的error日誌。

b、配置文件在根目錄下

一、工程目錄:

 

二、 log4j2.xml配置文件:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <Configuration status="INFO">
 3     <properties>
 4         <!--變量定義 -->
 5         <Property name="baseDir">/data/logs/</Property>
 6         <property name="log_pattern">%-d{yyyy-MM-dd HH:mm:ss.SSS} [%t:%r] [%F:%L] - [%p] %m%n</property>
 7         <property name="file_name">info.log</property>
 8         <property name="error_file_name">error.log</property>
 9         <property name="warn_file_name">warn.log</property>
10         <property name="rolling_file_name">wdmsg-%d{yyyy-MM-dd-HH}.log.%i</property>
11         <!-- 日誌切割的最小單位 -->
12         <property name="every_file_size">100M</property> 
13     </properties>
14 
15     <Appenders>
16         <!--輸出控制檯的配置 -->
17         <Console name="console" target="SYSTEM_OUT">
18             <!--控制檯只輸出level及以上級別的信息(onMatch),其餘的直接拒絕(onMismatch) -->
19             <ThresholdFilter level="INFO" onMatch="ACCEPT" />
20             <!--輸出日誌的格式 -->
21             <PatternLayout pattern="${log_pattern}" />
22         </Console>
23         
24         <!-- 輸出不一樣級別的日誌到不一樣的文件下 -->
25         <RollingFile name="infoFile" fileName="${baseDir}${file_name}" filePattern="${baseDir}${rolling_file_name}">
26             <PatternLayout pattern="${log_pattern}" />
27             <Filters>
28                 <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL" />
29                 <ThresholdFilter level="INFO" onMatch="ACCEPT" />
30             </Filters>
31             <SizeBasedTriggeringPolicy size="${every_file_size}" />
32         </RollingFile>
33         <RollingFile name="warnFile" fileName="${baseDir}${warn_file_name}" filePattern="${baseDir}${rolling_file_name}">
34             <PatternLayout pattern="${log_pattern}" />
35             <Filters>
36                 <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL" />
37                 <ThresholdFilter level="WARN" onMatch="ACCEPT" />
38             </Filters>
39             <SizeBasedTriggeringPolicy size="${every_file_size}" />
40         </RollingFile>
41         <RollingFile name="errorFile" fileName="${baseDir}${error_file_name}" filePattern="${baseDir}${rolling_file_name}">
42             <PatternLayout pattern="${log_pattern}" />
43             <ThresholdFilter level="ERROR" onMatch="ACCEPT" />
44             <SizeBasedTriggeringPolicy size="${every_file_size}" />
45         </RollingFile>
46     </Appenders>
47     <Loggers>
48         <!--創建一個默認的root的logger,須要在root的level中指定輸出的級別, -->
49         <Root level="all">
50             <appender-ref ref="console" />
51             <appender-ref ref="infoFile" />
52             <appender-ref ref="warnFile" />
53             <appender-ref ref="errorFile" />
54         </Root>
55     </Loggers>
56 </Configuration>

三、測試類與上個例子同樣,測試結果以下:

五月 24, 2017 7:47:42 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getDefaultTestExecutionListenerClassNames
INFO: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
五月 24, 2017 7:47:42 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
五月 24, 2017 7:47:42 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
五月 24, 2017 7:47:42 下午 org.springframework.test.context.support.DefaultTestContextBootstrapper getTestExecutionListeners
INFO: Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@4f6f76a8, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1ed73856, org.springframework.test.context.support.DirtiesContextTestExecutionListener@43b3a5eb]
五月 24, 2017 7:47:42 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [META-INF/spring/springContext.xml]
五月 24, 2017 7:47:43 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@1a0efbfe: startup date [Wed May 24 19:47:43 CST 2017]; root of context hierarchy
2017-05-24 19:47:43.160 [main:982] [TestLog4j2.java:22] - [INFO] info message
2017-05-24 19:47:43.161 [main:983] [TestLog4j2.java:23] - [WARN] warn message
2017-05-24 19:47:43.161 [main:983] [TestLog4j2.java:24] - [ERROR] error message
五月 24, 2017 7:47:43 下午 org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@1a0efbfe: startup date [Wed May 24 19:47:43 CST 2017]; root of context hierarchy

控制檯打印正常,看下日誌文件,我配置的路徑是:/data/logs/

分別生成了三個文件,咱們來看下具體內容:

c、自定義配置文件的路徑

一、工程目錄:

log4j2.xml不是放在根目錄下,而是放在classpath:META-INF/目錄下。

二、web.xml的配置,用於查找配置文件

三、容器啓動後並訪問含有打印日誌的類,控制檯消息以下:

INFO: Loading XML bean definitions from class path resource [META-INF/spring/springMVC.xml]
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
INFO: Mapped "{[/index/{id}],methods=[GET],params=[age=14]}" onto public java.lang.String com.cd.mvc.controller.DemoController.index(int,javax.servlet.ServletRequest,org.springframework.ui.Model)
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: WebApplicationContext for namespace 'spring-servlet': startup date [Fri May 26 10:42:03 CST 2017]; parent: Root WebApplicationContext
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
INFO: Looking for @ControllerAdvice: WebApplicationContext for namespace 'spring-servlet': startup date [Fri May 26 10:42:03 CST 2017]; parent: Root WebApplicationContext
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping registerHandler
INFO: Mapped URL path [/out/index] onto handler '/out/index'
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
INFO: Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'
五月 26, 2017 10:42:03 上午 org.springframework.web.servlet.DispatcherServlet initServletBean
INFO: FrameworkServlet 'spring': initialization completed in 730 ms
五月 26, 2017 10:42:03 上午 org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8210"]
五月 26, 2017 10:42:03 上午 org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
五月 26, 2017 10:42:03 上午 org.apache.catalina.startup.Catalina start
INFO: Server startup in 1921 ms
10:42:11.611 [http-bio-8210-exec-3] ERROR com.cd.mvc.controller.DemoController - error id =33

這個明顯不是預計的結果,這裏我折騰的好久,始終沒有找到問題的緣由,先在這標記求助下!!!

配置文件log4j2.xml存放的路徑不在根目錄下,可是web.xml中有對應查找文件的相關配置。但是在容器啓動過程當中卻提示No log4j2 configuration file found,使用log4j2默認的配置,日誌輸出見最後一行。

相關文章
相關標籤/搜索