log4j2 項(xiàng)目日志組件的實(shí)例代碼
在項(xiàng)目運(yùn)行過(guò)程中,常常需要進(jìn)行功能調(diào)試以及用戶行為的跟蹤和記錄,部分人習(xí)慣使用System.out,但這并不建議,它僅僅是使用方便但不便于維護(hù)也無(wú)擴(kuò)展性。相比log4j的話,log4j可以控制日志信息的輸送目的地、輸出格式以及級(jí)別等等,使我們能夠更加細(xì)致地控制日志的生成過(guò)程。
Log4j2是對(duì)Log4j1的升級(jí),在性能和功能上有顯著的改進(jìn),包括多線程中吞吐量的增強(qiáng)、占位符的支持、配置文件自動(dòng)重新加載等
一、入門(mén)介紹
1、下載jar包
pox.xml
<dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.10.0</version> </dependency> </dependencies>
2、配置文件
Log4j包含四個(gè)配置工廠實(shí)現(xiàn):JSON、YAML、properties、XML,本文介紹常用的方式XML。
Log4j具有在初始化期間自動(dòng)配置自身的能力。當(dāng)Log4j啟動(dòng)時(shí),它將定位類路徑下所有符合名稱的文件,優(yōu)先級(jí)順序:log4j2-test.properties > log4j2-test.xml > log4j2.properties > log4j2.xml
3、一個(gè)簡(jiǎn)單的實(shí)例
xml配置:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <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="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
java代碼:
private static final Logger logger = LogManager.getLogger(MyApp.class); @Test public void testLog4j(){ logger.info("hello world!"); } }
控制臺(tái)信息
22:17:47.146 [main] INFO MyApp - hello world!
二、模塊介紹
<Configuration>
屬性 | 描述 |
monitorInterval | 如果文件被修改了,指定時(shí)間后會(huì)重新加載配置。單位秒,最小值是5 |
packages | 以逗號(hào)隔開(kāi)的包名列表,用于搜索插件,比如自定義filter、appender等。插件僅會(huì)加載一次,所以要想修改后生效必須重啟項(xiàng)目 |
status | 內(nèi)部日志級(jí)別,設(shè)置值為debug可以在控制臺(tái)上清晰地看到整個(gè)日志事件流程,所使用的Logger是org.apache.logging.log4j.core.LOGGER |
strict | 允許使用嚴(yán)格的XML格式。不支持JSON配置 |
verbose | 在加載插件時(shí)啟用診斷信息 |
<Appenders>
Log4j允許將日志請(qǐng)求打印到多個(gè)目的地。在log4j語(yǔ)言中,輸出目的地稱為Appender。目前,appender存在于控制臺(tái)、文件、遠(yuǎn)程套接字服務(wù)器、Apache Flume、JMS、遠(yuǎn)程UNIX Syslog守護(hù)進(jìn)程和各種數(shù)據(jù)庫(kù)api中。以下介紹幾種比較常用的appender,如需了解更多可以到官網(wǎng)上進(jìn)行查閱。
1、ConsoleAppender
輸出到控制臺(tái),<Console>
參數(shù)名稱 |
類型 |
描述 |
filter |
Filter |
過(guò)濾器 |
layout |
Layout |
日志輸出格式 |
follow |
boolean |
|
direct |
boolean |
|
name |
String |
Appender的名稱 |
ignoreExceptions |
boolean |
默認(rèn)true,忽略寫(xiě)入異常 |
target |
String |
SYSTEM_OUT或SYSTEM_ERR,默認(rèn)是SYSTEM_OUT |
2、FileAppender
輸出到文件,<File>
參數(shù) |
類型 |
描述 |
---|---|---|
append |
boolean |
默認(rèn)是true,新記錄將追加到文件尾部 |
bufferedIO |
boolean |
默認(rèn)是true,使用緩沖區(qū)可以顯著地提高性能 |
bufferSize |
int |
當(dāng)bufferedIO是true時(shí),這個(gè)屬性緩沖區(qū)大小,默認(rèn)是8192字節(jié)。 |
createOnDemand |
boolean |
appender按需創(chuàng)建文件。只有當(dāng)一個(gè)日志事件通過(guò)所有過(guò)濾器并被路由到這個(gè)appender時(shí),appender才會(huì)創(chuàng)建這個(gè)文件。默認(rèn)值為假 |
filter |
Filter |
一個(gè)過(guò)濾器來(lái)確定事件是否應(yīng)該由這個(gè)Appender處理。使用復(fù)合過(guò)濾器可以使用多個(gè)篩選器 |
fileName |
String |
要寫(xiě)入的文件的名稱。如果文件或它的任何父目錄不存在,它們將被創(chuàng)建 |
immediateFlush |
boolean |
默認(rèn)true,每次寫(xiě)入后都將有一個(gè)刷新。這將保證緩沖區(qū)的數(shù)據(jù)被寫(xiě)入磁盤(pán),但可能會(huì)影響性能。 |
layout |
Layout |
日志格式 |
locking |
boolean |
文件鎖,默認(rèn)false |
name |
String |
Appender的名稱 |
ignoreExceptions |
boolean |
默認(rèn)true,忽略寫(xiě)入異常 |
filePermissions |
String |
定義文件權(quán)限 例: rw------- or rw-rw-rw- etc... |
fileOwner |
String |
定義文件所有者 |
fileGroup |
String |
定義文件組 |
3、JDBCAppender
JDBCAppender使用標(biāo)準(zhǔn)JDBC將日志事件寫(xiě)入到關(guān)系數(shù)據(jù)庫(kù)表中。它可以配置為使用JNDI數(shù)據(jù)源或自定義工廠方法獲得JDBC連接。無(wú)論采用哪種方法,都必須由連接池來(lái)支持。
否則,日志記錄性能將受到極大的影響。
如果已配置的JDBC驅(qū)動(dòng)程序支持批處理語(yǔ)句,并且將緩沖區(qū)大小配置為一個(gè)正數(shù),那么日志事件將被批處理。
(1)<JDBC>
參數(shù) |
類型 |
描述 |
---|---|---|
name |
String |
必須,appender的名稱 |
ignoreExceptions |
boolean |
默認(rèn)true,忽略日志事件異常 |
filter |
Filter |
過(guò)濾器 |
bufferSize |
int |
如果一個(gè)大于0的整數(shù),這將導(dǎo)致appender緩沖日志事件,并在緩沖區(qū)達(dá)到該大小時(shí)刷新寫(xiě)入數(shù)據(jù) |
connectionSource |
ConnectionSource |
必須,可被檢索到的數(shù)據(jù)庫(kù)連接 |
tableName |
String |
必須,插入日志事件的數(shù)據(jù)表名 |
columnConfigs |
ColumnConfig[] |
必須,需要插入到數(shù)據(jù)庫(kù)的字段,由多個(gè)<Column>元素組成 |
columnMappings |
ColumnMapping[] |
必須,字段映射配置 |
(2)使用<DataSource>來(lái)獲得JDBC的連接,這里僅列出jndi:
參數(shù) | 類型 | 描述 |
---|---|---|
jndiName | String | 必需的,如已配置的jndi為jdbc/LoggingDatabase,那此處的值為java:comp/env/jdbc/LoggingDatabase。數(shù)據(jù)源必須由連接池來(lái)支持;否則,日志記錄將非常緩慢。 |
(3)使用<Column>來(lái)指定要寫(xiě)入表中的哪些列,以及如何對(duì)它們進(jìn)行寫(xiě)入。它沒(méi)有SQL注入漏洞。
參數(shù) | 類型 | 描述 |
---|---|---|
name | String |
必須,表字段名稱 |
pattern | String |
使用PatternLayout模式插入值,注:同一個(gè)Column元素中,patter、literal、isEventTimestamp3個(gè)屬性只能存在一個(gè) |
literal | String |
該值將直接包含在SQL語(yǔ)句中執(zhí)行,比如:rand()函數(shù)將生成隨機(jī)數(shù),類似myibats中的${} |
isEventTimestamp | boolean |
是否時(shí)間格式j(luò)ava.sql.Types.TIMESTAMP |
isUnicode | boolean |
除非指定pattern,否則該屬性將被忽略。如果是true,該值將插入U(xiǎn)nicode。否則,該值將被插入非Unicode。 |
isClob | boolean |
除非指定pattern,否則該屬性將被忽略。如果是true,該值將插入CLOB,否則將插入varchar、nvarchar |
實(shí)例:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <JDBC name="databaseAppender" tableName="dbo.application_log"> <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" /> <Column name="eventDate" isEventTimestamp="true" /> <Column name="level" pattern="%level" /> <Column name="logger" pattern="%logger" /> <Column name="message" pattern="%message" /> <Column name="exception" pattern="%ex{full}" /> </JDBC> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
<PatternLayout>
(1)日期,%d / %date
Pattern |
示例 |
---|---|
%d{DEFAULT} |
2012-11-02 14:34:02,781 |
%d{ISO8601} |
2012-11-02T14:34:02,781 |
%d{ISO8601_BASIC} |
20121102T143402,781 |
%d{ABSOLUTE} |
14:34:02,781 |
%d{DATE} |
02 Nov 2012 14:34:02,781 |
%d{COMPACT} |
20121102143402781 |
%d{HH:mm:ss,SSS} |
14:34:02,781 |
%d{dd MMM yyyy HH:mm:ss,SSS} |
02 Nov 2012 14:34:02,781 |
%d{HH:mm:ss}{GMT+0} |
18:34:02 |
%d{UNIX} |
1351866842 |
%d{UNIX_MILLIS} |
1351866842781 |
當(dāng)然你也可以自定義格式,比如 %d{yyyy-MM-dd HH:mm:ss}
(2)記錄器,%c / %logger
Conversion Pattern |
Logger Name |
結(jié)果 |
---|---|---|
%c{1} |
org.apache.commons.Foo |
Foo |
%c{2} |
org.apache.commons.Foo |
commons.Foo |
%c{10} |
org.apache.commons.Foo |
org.apache.commons.Foo |
%c{-1} |
org.apache.commons.Foo |
apache.commons.Foo |
%c{-2} |
org.apache.commons.Foo |
commons.Foo |
%c{-10} |
org.apache.commons.Foo |
org.apache.commons.Foo |
%c{1.} |
org.apache.commons.Foo |
o.a.c.Foo |
%c{1.1.~.~} |
org.apache.commons.test.Foo |
o.a.~.~.Foo |
%c{.} |
org.apache.commons.test.Foo |
....Foo |
{?} - ?是正整數(shù)時(shí)表示從右邊開(kāi)始取n個(gè)部分,負(fù)整數(shù)表示從左邊開(kāi)始移除n個(gè)部分,那為什么%c{-10}是完整的名稱我也不清楚,歡迎留言
(3)日志信息,%m / %msg / %message
(4)日志級(jí)別,%level
<Filter>
log4j2自帶多種filter供直接使用,也可以由我們自己來(lái)定義filter:
MyFilter.java
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.filter.AbstractFilter; import org.apache.logging.log4j.message.Message; @Plugin(name = "MyFilter", category = "Core", elementType = "filter", printObject = true) public final class MyFilter extends AbstractFilter { private final Level level; private MyFilter(Level level, Result onMatch, Result onMismatch) { super(onMatch, onMismatch); this.level = level; } public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) { return filter(level); } public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) { return filter(level); } public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) { return filter(level); } @Override public Result filter(LogEvent event) { return filter(event.getLevel()); } private Result filter(Level level) { /* * 業(yè)務(wù)邏輯 * */ return level.isMoreSpecificThan(this.level) ? onMatch : onMismatch; } @Override public String toString() { return level.toString(); } @PluginFactory public static MyFilter createFilter(@PluginAttribute(value = "level", defaultString = "ERROR") Level level, @PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch, @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) { return new MyFilter(level, onMatch, onMismatch); } }
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" monitorInterval="5" packages="your packages" verbose="false" strict="true"> <Appenders> <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="true"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %level %logger{10} - %msg"/> <MyFilter level="info" onMatch="ACCEPT"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
補(bǔ)充:
在實(shí)際應(yīng)用中,有時(shí)需要對(duì)用戶的訪問(wèn)信息進(jìn)行記錄,比如請(qǐng)求參數(shù)、用戶id等等。在log4j1中我們會(huì)使用MDC和NDC來(lái)存儲(chǔ)應(yīng)用程序的上下文信息,而log4j2使用ThreadContext來(lái)實(shí)現(xiàn)MDC和NDC兩者的功能。
(1)NDC采用類似棧的機(jī)制來(lái)存儲(chǔ)上下文信息,線程獨(dú)立。
在PatternLayout中使用 %x 來(lái)輸出,注意x是小寫(xiě)。
實(shí)例:
Test.java
ThreadContext.push("hello world!");
log4j2.xml
<Column name="tip" pattern="%x" />
(2)MDC采用類似map的機(jī)制來(lái)存儲(chǔ)信息,線程獨(dú)立。
在PatternLayout中使用 %X{userId} 來(lái)輸出,注意X是大寫(xiě)。
實(shí)例:
Test.java
ThreadContext.put("userId","1");
log4j2.xml
<Column name="userId" pattern="%X{userId}" />
注意使用完后調(diào)用clearAll()清除上下文映射和堆棧。
api:http://logging.apache.org/log4j/2.x/javadoc.html
官網(wǎng)地址:https://logging.apache.org/log4j/2.x/index.html
以上這篇log4j2 項(xiàng)目日志組件的實(shí)例代碼就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot單文件下載和多文件壓縮zip下載的實(shí)現(xiàn)
這篇文章主要介紹了springboot單文件下載和多文件壓縮zip下載的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11SpringBoot多環(huán)境切換的靈活配置詳細(xì)教程
在真實(shí)項(xiàng)目開(kāi)發(fā)的時(shí)候,一定會(huì)有多個(gè)環(huán)境,下面這篇文章主要給大家介紹了關(guān)于SpringBoot多環(huán)境切換靈活配置的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04Java實(shí)現(xiàn)md5和base64加密解密的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)md5和base64加密解密的示例代碼,幫助大家更好的利用Java加密解密文件,感興趣的朋友可以了解下2020-09-09Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南
這篇文章主要介紹了Spring的BeanUtils.copyProperties屬性復(fù)制避坑指南,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08詳解Java分布式緩存系統(tǒng)中必須解決的四大問(wèn)題
分布式緩存系統(tǒng)是三高架構(gòu)中不可或缺的部分,極大地提高了整個(gè)項(xiàng)目的并發(fā)量、響應(yīng)速度,但它也帶來(lái)了新的需要解決的問(wèn)題,分別是: 緩存穿透、緩存擊穿、緩存雪崩和緩存一致性問(wèn)題。本文將詳細(xì)講解一下這四大問(wèn)題,需要的可以參考一下2022-04-04spring boot aop 記錄方法執(zhí)行時(shí)間代碼示例
這篇文章主要介紹了spring boot aop 記錄方法執(zhí)行時(shí)間代碼示例,分享了相關(guān)代碼,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02