需求:將Mybatis的執(zhí)行SQL,按天存日志文件。項(xiàng)目使用的是log4j2。
原先項(xiàng)目,都是將所有日志通通打印到控制臺(tái)?,F(xiàn)在需要將系統(tǒng)接收用戶請(qǐng)求后,Mybatis的執(zhí)行SQL,按天存日志文件。
當(dāng)時(shí)在想:
把Mybatis的SQL打印到控制臺(tái)容易實(shí)現(xiàn),
日志按Level級(jí)別 按天存文件也容易實(shí)現(xiàn),
但如何單獨(dú)把Mybatis的SQL,按天存日志文件呢?
于是找了MyBatis日志配置說明
http://www.mybatis.org/mybatis-3/zh/logging.html
Mybatis 的內(nèi)置日志工廠提供日志功能,內(nèi)置日志工廠將日志交給以下其中一種工具作代理:
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j
- JDK logging
MyBatis 內(nèi)置日志工廠基于運(yùn)行時(shí)自省機(jī)制選擇合適的日志工具。它會(huì)使用第一個(gè)查找得到的工具(按上文列舉的順序查找)。如果一個(gè)都未找到,日志功能就會(huì)被禁用。
可以在mybatis-config.xml 中,設(shè)定使用的日志組件。
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J2"/>
...
</settings>
</configuration>
logImpl 可選的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是實(shí)現(xiàn)了接口org.apache.ibatis.logging.Log 的,且構(gòu)造方法是以字符串為參數(shù)的類的完全限定名。
通過學(xué)習(xí)發(fā)現(xiàn):Mybatis 中 SQL 語句的日志級(jí)別被設(shè)為DEBUG(JDK 日志設(shè)為 FINE),SQL執(zhí)行結(jié)果的日志級(jí)別為 TRACE(JDK 日志設(shè)為 FINER)。
所以,如果某些查詢可能會(huì)返回龐大的結(jié)果集,此時(shí)只想記錄其執(zhí)行的 SQL 語句而不想記錄結(jié)果該怎么辦,只要將日志級(jí)別調(diào)整為 DEBUG 即可達(dá)到目的。
可見:無論使用哪個(gè)日志組件、無論打印什么內(nèi)容,均是按日志級(jí)別進(jìn)行輸出的。所以在本需求中,Mybatis的SQL按debug級(jí)別輸出到指定地方即可。
無論是Mybatis框架,還是Spring、Java Mail框架,如果想看到框架底層運(yùn)行的日志信息,配置日志級(jí)別為debug即可。
再次說明下,Mybatis 內(nèi)置日志工廠將日志交給其中一種日志工具作代理。具體怎么做,由使用的日志工具決定,因此本需求MyBatis執(zhí)行SQL的文件保存,是取決于使用的log4j2日志組件實(shí)現(xiàn)。
下面就來看一下log4j2具體的配置。
在log4j2中, 共有8個(gè)輸出級(jí)別,按照從低到高為:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。
log4j2 的配置文件支持 xml、json、jsn 三種格式,默認(rèn)情況下由系統(tǒng)自動(dòng)加載,其要在classpath 可加載到的目錄下。
日志配置文件主要配置2大類
1、配置輸出源<Appenders>:日志輸出到哪里。如控制臺(tái)、file等
2、具體的日志配置<Loggers>:配置name,啟用哪個(gè)Appender,以及日志級(jí)別等。
下面給出本需求的簡(jiǎn)單配置實(shí)現(xiàn):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR" monitorInterval="600">
<!-- configure.status 為設(shè)置日志輸出級(jí)別,級(jí)別如下:OFF 、FATAL 、ERROR、WARN、INFO、DEBUG、TRACE、ALL -->
<!-- configure.monitorInterval 監(jiān)控間隔 指log4j2每隔600秒(10分鐘),自動(dòng)監(jiān)控該配置文件是否有變化,如果變化,則自動(dòng)根據(jù)文件內(nèi)容重新配置 -->
<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:級(jí)別、使用的輸出地-->
<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文件配置,根節(jié)點(diǎn)是<Configuration>,它有2個(gè)可選屬性:
- status 為設(shè)置日志輸出級(jí)別,級(jí)別如下:OFF 、FATAL 、ERROR、WARN、INFO、DEBUG、TRACE 、ALL
- monitorInterval 監(jiān)控間隔 指log4j2每隔600秒(10分鐘),自動(dòng)監(jiān)控該配置文件是否有變化,如果變化,則自動(dòng)根據(jù)文件內(nèi)容重新配置。
1、配置輸出源<Appenders>:
配置日志輸出到哪里。如控制臺(tái)、file等。
<Appenders>下通常有一個(gè)<Console> 表示日志都輸出到控制臺(tái),方便開發(fā)期間進(jìn)行查看。
另一個(gè)是<RollingRandomAccessFile>,按時(shí)間和文件大小滾動(dòng)(rollover)的RollingRandomAccessFile Appender,名字真是夠長(zhǎng),但不光只是名字長(zhǎng),相比RollingFileAppender有很大的性能提升,官網(wǎng)宣稱是20-200%。
rollover的意思是當(dāng)滿足一定條件(如文件達(dá)到了指定的大小,達(dá)到了指定的時(shí)間)后,就重命名原日志文件進(jìn)行歸檔,并生成新的日志文件用于log寫入。如果還設(shè)置了一定時(shí)間內(nèi)允許歸檔的日志文件的最大數(shù)量,將對(duì)過舊的日志文件進(jìn)行刪除操作。
這里說的“滿足一定條件”,是需要觸發(fā)的,需要配置基于時(shí)間的、或基于日志文件大小的觸發(fā)策略,也就是如下配置:
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
關(guān)鍵點(diǎn)在于 filePattern后的日期格式,以及TimeBasedTriggeringPolicy的interval,日期格式精確到哪一位,interval也精確到哪一個(gè)單位。在本示例中,filePattern最小單位是天,interval=1也就是一天一個(gè)日志文件。
TimeBasedTriggeringPolicy基于時(shí)間的觸發(fā)策略
| 屬性 | 解釋 |
|---|---|
| interval | (integer)該屬性是相對(duì) RollingFile.filePattern 中的 %d{yyyy-MM-dd}值,例:filePattern=”xxx%d{yyyy-MM-dd}xx” interval=”2” 表示將2天一個(gè)日志文件;filePattern=”xxx%d{yyyy-MM-dd-HH}xx” interval=”1”表示一個(gè)小時(shí)一個(gè)日志文件 |
| modulate | (boolean)以0點(diǎn)為邊界進(jìn)行偏移計(jì)算 |
2、具體的日志配置<Loggers>:
配置name,啟用哪個(gè)Appender,以及日志級(jí)別等。
重點(diǎn)說明
<Logger name="com.ljheee.app.dao" level="debug" additivity="true">
<appender-ref ref="fileLogger" level="debug"/>
</Logger>
MyBatis支持多種粒度的日志記錄:
1、可以記錄某個(gè)映射器接口的日志
將name設(shè)為name="com.ljheee.app.dao.UserMapper"
就會(huì)記錄 com.ljheee.app.dao.UserMapper 的詳細(xì)執(zhí)行操作,且僅記錄應(yīng)用中其它類的錯(cuò)誤信息(若有)。
2、還可以將日志的記錄方式從接口級(jí)別切換到語句級(jí)別,從而實(shí)現(xiàn)更細(xì)粒度的控制。如下配置只對(duì) select 語句記錄日志:
將name設(shè)為name="com.ljheee.app.dao.UserMapper.select"
3、當(dāng)然也可以按實(shí)例配置到包級(jí)別,在DAO層,將包下所有MyBatis的mapper接口均使用日志記錄。
小結(jié):
log4j2 是Apache開發(fā)的一款log4j的升級(jí)產(chǎn)品,在某些特定的場(chǎng)景上面,甚至可以比之前的速度快上10倍。在保證log的組件更加快速的同時(shí),同時(shí)所需的內(nèi)存更加少。
上面在說RollingRandomAccessFile時(shí),也說到性能很高,因?yàn)閘og4j2 內(nèi)部使用了Disruptor高性能并發(fā)框架,輸出日志采用異步輸出,極高地提升了日志輸出性能,因此也建議將后續(xù)的應(yīng)用日志方式,切換到log4j2。
log4j2 配置示例https://howtodoinjava.com/log4j2/log4j-2-xml-configuration-example/
log4j2文檔https://logging.apache.org/log4j/2.x/manual/appenders.html