log4j2實戰--將MyBatis執行SQL記錄到檔案,按天分存
需求:
將Mybatis的執行SQL,按天存日誌檔案。專案使用的是log4j2。
原先專案,都是將所有日誌通通列印到控制檯。現在需要將系統接收使用者請求後,Mybatis的執行SQL,按天存日誌檔案。
當時在想:
把Mybatis的SQL列印到控制檯容易實現,
日誌按Level級別 按天存檔案也容易實現,
但如何單獨把Mybatis的SQL,按天存日誌檔案呢?
Mybatis 的內建日誌工廠提供日誌功能,內建日誌工廠將日誌交給以下其中一種工具作代理:
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j
- JDK logging
MyBatis 內建日誌工廠基於執行時自省機制選擇合適的日誌工具。它會使用第一個查詢得到的工具(按上文列舉的順序查詢)。如果一個都未找到,日誌功能就會被禁用。
可以在mybatis-config.xml 中,設定使用的日誌元件。
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J2"/>
...
</settings>
</configuration>
logImpl 可選的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是實現了介面org.apache.ibatis.logging.Log
通過學習發現:Mybatis 中 SQL 語句的日誌級別被設為DEBUG(JDK 日誌設為 FINE),SQL執行結果的日誌級別為 TRACE(JDK 日誌設為 FINER)。
所以,如果某些查詢可能會返回龐大的結果集,此時只想記錄其執行的 SQL 語句而不想記錄結果該怎麼辦,只要將日誌級別調整為 DEBUG 即可達到目的。
可見:無論使用哪個日誌元件、無論列印什麼內容,均是按日誌級別進行輸出的。所以在本需求中,Mybatis的SQL按debug級別輸出到指定地方即可。
無論是Mybatis框架,還是Spring、Java Mail框架,如果想看到框架底層執行的日誌資訊,配置日誌級別為debug即可。
再次說明下,Mybatis 內建日誌工廠將日誌交給其中一種日誌工具作代理。具體怎麼做,由使用的日誌工具決定,因此本需求MyBatis執行SQL的檔案儲存,是取決於使用的log4j2日誌元件實現。
下面就來看一下log4j2具體的配置。
在log4j2中, 共有8個輸出級別,按照從低到高為:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。
log4j2 的配置檔案支援 xml、json、jsn 三種格式,預設情況下由系統自動載入,其要在classpath 可載入到的目錄下。
日誌配置檔案主要配置2大類
1、配置輸出源<Appenders>:日誌輸出到哪裡。如控制檯、file等
2、具體的日誌配置<Loggers>:配置name,啟用哪個Appender,以及日誌級別等。
下面給出本需求的簡單配置實現:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR" monitorInterval="600">
<!-- configure.status 為設定日誌輸出級別,級別如下:OFF 、FATAL 、ERROR、WARN、INFO、DEBUG、TRACE、ALL -->
<!-- configure.monitorInterval 監控間隔 指log4j2每隔600秒(10分鐘),自動監控該配置檔案是否有變化,如果變化,則自動根據檔案內容重新配置 -->
<Properties>
<property name="pattern">%d{yyyy/MM/dd HH:mm:ss.SSS} [%p] %t %c %m%n</property>
<property name="basePath">/Users/lijianhua/Documents/my-log</property>
</Properties>
<!--配置appenders源:日誌輸出的地址-->
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}"/>
</Console>
<RollingRandomAccessFile name="fileLogger"
fileName="${basePath}/mybatis-sql.log"
filePattern="${basePath}/mybatis-sql-%d{yyyy-MM-dd}.log"
append="true">
<PatternLayout pattern="${pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
</RollingRandomAccessFile>
</Appenders>
<!--配置logers:級別、使用的輸出地-->
<Loggers>
<Logger name="com.ljheee.app.dao" level="debug" additivity="true">
<appender-ref ref="fileLogger" level="debug"/>
</Logger>
<Root level="info" additivity="false">
<appender-ref ref="console"/>
</Root>
</Loggers>
</Configuration>
通常log4j 採用properties檔案配置。log4j2 採用xml檔案配置。
log4j2 的xml檔案配置,根節點是<Configuration>,它有2個可選屬性:
- status 為設定日誌輸出級別,級別如下:OFF 、FATAL 、ERROR、WARN、INFO、DEBUG、TRACE 、ALL
- monitorInterval 監控間隔 指log4j2每隔600秒(10分鐘),自動監控該配置檔案是否有變化,如果變化,則自動根據檔案內容重新配置。
1、配置輸出源<Appenders>:
配置日誌輸出到哪裡。如控制檯、file等。
<Appenders>下通常有一個<Console> 表示日誌都輸出到控制檯,方便開發期間進行檢視。
另一個是<RollingRandomAccessFile>,按時間和檔案大小滾動(rollover)的RollingRandomAccessFile Appender,名字真是夠長,但不光只是名字長,相比RollingFileAppender有很大的效能提升,官網宣稱是20-200%。
rollover的意思是當滿足一定條件(如檔案達到了指定的大小,達到了指定的時間)後,就重新命名原日誌檔案進行歸檔,並生成新的日誌檔案用於log寫入。如果還設定了一定時間內允許歸檔的日誌檔案的最大數量,將對過舊的日誌檔案進行刪除操作。
這裡說的“滿足一定條件”,是需要觸發的,需要配置基於時間的、或基於日誌檔案大小的觸發策略,也就是如下配置:
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
關鍵點在於 filePattern後的日期格式,以及TimeBasedTriggeringPolicy的interval,日期格式精確到哪一位,interval也精確到哪一個單位。在本示例中,filePattern最小單位是天,interval=1也就是一天一個日誌檔案。
TimeBasedTriggeringPolicy基於時間的觸發策略
屬性 | 解釋 |
---|---|
interval | (integer)該屬性是相對 RollingFile.filePattern 中的 %d{yyyy-MM-dd}值,例:filePattern=”xxx%d{yyyy-MM-dd}xx” interval=”2” 表示將2天一個日誌檔案;filePattern=”xxx%d{yyyy-MM-dd-HH}xx” interval=”1”表示一個小時一個日誌檔案 |
modulate | (boolean)以0點為邊界進行偏移計算 |
2、具體的日誌配置<Loggers>:
配置name,啟用哪個Appender,以及日誌級別等。
重點說明
<Logger name="com.ljheee.app.dao" level="debug" additivity="true">
<appender-ref ref="fileLogger" level="debug"/>
</Logger>
MyBatis支援多種粒度的日誌記錄:
1、可以記錄某個對映器介面的日誌
將name設為name="com.ljheee.app.dao.UserMapper"
就會記錄 com.ljheee.app.dao.UserMapper 的詳細執行操作,且僅記錄應用中其它類的錯誤資訊(若有)。
2、還可以將日誌的記錄方式從介面級別切換到語句級別,從而實現更細粒度的控制。如下配置只對 select 語句記錄日誌:
將name設為name="com.ljheee.app.dao.UserMapper.select"
3、當然也可以按例項配置到包級別,在DAO層,將包下所有MyBatis的mapper介面均使用日誌記錄。
小結:
log4j2 是Apache開發的一款log4j的升級產品,在某些特定的場景上面,甚至可以比之前的速度快上10倍。在保證log的元件更加快速的同時,同時所需的記憶體更加少。
上面在說RollingRandomAccessFile時,也說到效能很高,因為log4j2 內部使用了Disruptor高效能併發框架,輸出日誌採用非同步輸出,極高地提升了日誌輸出效能,因此也建議將後續的應用日誌方式,切換到log4j2。