常用日志门面和日志实现
一、什么是日志門面和日志實現
因為日志實現,可能會有一些代碼的優化和改動,避免影響用戶在項目中的使用,使用日志門面這些統一的接口,假設在實現層代碼做了更改,用戶在項目中使用日志而調用的接口等等都是不會受影響的。
在實際使用中,是選擇一個抽象層的日志門面搭配一個底層日志實現來使用的。
SpringBoot中默認選擇的搭配是:slf4j+logback
下面分別了解一下以上提到的各種門面和實現。
-
JCL:最后一次版本更新停在了2014年,后來沒有繼續維護更新,一般不考慮選用。
-
slf4j:這里提一下日志實現里面的log4j和logback,這兩個實現和門面slf4j都是同一個人寫的,他先寫了log4j后,覺得性能可以再做優化,又寫了logback,為了有更加適配的門面,自己又為log4j和logback量身打造了門面slf4j。所以這三者里面最優的搭配當然是slf4j+logback。
-
JUL:是java.util.logging包下提供的日志實現。
-
log4j2:在log4j問世之后,apache公司發現了日志市場,自家也開發了一款叫log4j2的產品。
二、日志門面
SLF4J
簡單日志門面(Simple Logging Facade For Java) SLF4J主要是為了給Java日志訪問提供一套標準、規范的API框架,其主要意義在于提供接口,具體的實現可以交由其他日志框架,例如log4j和logback等。 當然slf4j自己也提供了功能較為簡單的實現,但是一般很少用到。對于一般的Java項目而言,日志框架會選擇slf4j-api作為門面,配上具體的實現框架(log4j、logback等),中間使用橋接器完成橋接。
官方網站: https://www.slf4j.org/
適配器使用: http://www.slf4j.org/manual.html
橋接器的使用: http://www.slf4j.org/legacy.html
- 常見日志門面;JCL、slf4j
三、日志實現
- LOG4J
Log4j是Apache下的一款開源的日志框架,通過在項目中使用 Log4J,我們可以控制日志信息輸出到控制臺、文件、甚至是數據庫中。我們可以控制每一條日志的輸出格式,通過定義日志的輸出級別,可以更靈活的控制日志的輸出過程。方便項目的調試。
- 常見的日志實現:JUL、log4j、logback、log4j2
四、log4j例子
- 導入依賴
- 代碼
- Log4j讀取的配置文件類型
- 日志的級別
- fatal 每個嚴重的錯誤事件將會導致應用程序的退出
- error 雖然發生錯誤事件,但仍然不影響系統的繼續運行
- warn 會出現潛在的錯誤情形 info 一般和在粗粒度級別上,強調應用程序的運行全程
- debug 一般用于細粒度級別上,對調試應用程序非常有幫助
- trace 程序追蹤,可以用于輸出程序運行中的變量,顯示執行的流程 一般只使用4個級別,優先級從高到低為 ERROR > WARN > INFO > DEBUG
- Log4j組件:Log4J 主要由 Loggers (日志記錄器)、Appenders(輸出端)和 Layout(日志格式化器)組成。
- Loggers 控制日志的輸出級別與日志是否輸出
- Appenders 指定日志的輸出方式(輸出到控制臺、文件 等)
- Layout 控制日志信息的輸出格式。
-
Loggers
日志記錄器,負責收集處理日志記錄 -
Appenders
用來指定日志輸出到哪個地方,可以同時指定日志的輸出目的地
-
Layouts
用于控制日志輸出內容的格式,讓我們可以使用各種需要的格式輸出日志
-
Layout的格式
在 log4j.properties 配置文件中,我們定義了日志輸出級別與輸出端,在輸出端中分別配置日志的輸出格式
- %m 輸出代碼中指定的日志信息
- %p 輸出優先級,及 DEBUG、INFO 等
- %n 換行符(Windows平臺的換行符為“\n”,Unix 平臺為 “\n”)
- %r 輸出自應用啟動到輸出該 log 信息耗費的毫秒數
- %c 輸出打印語句所屬的類的全名
- %t 輸出產生該日志的線程全名 %d 輸出服務器當前時間,默認為 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日HH:mm:ss}
- %l 輸出日志時間發生的位置,包括類名、線程、及在代碼中的行數。如:Test.main(Test.java:10)
- %F輸出日志消息產生時所在的文件名稱
- %L 輸出代碼中的行號
- %% 輸出一個 “%” 字符
- %5c 輸出category名稱,最小寬度是5,category<5,默認的情況下右對齊
- %-5c 輸出category名稱,最小寬度是5,category<5,"-"號指定左對齊,會有空格
- %.5c輸出category名稱,最大寬度是5,category>5,就會將左邊多出的字符截掉,<5不會有空格
- %20.30c category名稱<20補空格,并且右對齊,>30字符,就從左邊交遠銷出的字符截掉
- Appender的輸出
控制臺,文件,數據庫
- properties
數據庫表
CREATE TABLE `log` ( `log_id` int(11) NOT NULL AUTO_INCREMENT, `project_name` varchar(255) DEFAULT NULL COMMENT '目項名', `create_date` varchar(255) DEFAULT NULL COMMENT '創建時間', `level` varchar(255) DEFAULT NULL COMMENT '優先級', `category` varchar(255) DEFAULT NULL COMMENT '所在類的全名', `file_name` varchar(255) DEFAULT NULL COMMENT '輸出日志消息產生時所在的文件名稱 ', `thread_name` varchar(255) DEFAULT NULL COMMENT '日志事件的線程名', `line` varchar(255) DEFAULT NULL COMMENT '號行', `all_category` varchar(255) DEFAULT NULL COMMENT '日志事件的發生位置', `message` varchar(4000) DEFAULT NULL COMMENT '輸出代碼中指定的消息', PRIMARY KEY (`log_id`) );- 自定義Logger
五、Logback例子
-
Logback是由log4j創始人設計的另一個開源日志組件,性能比log4j要好。
-
官方網站:https://logback.qos.ch/index.html
- 導入依賴
- java代碼
- logback 讀取的配置文件類型
logback會依次讀取以下類型配置文件
- logback組件
- 配置信息
ConsoleAppender配置
FileAppender配置
<?xml version="1.0" encoding="UTF-8"?> <configuration><!-- 自定義屬性 可以通過${name}進行引用--><property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c %M %L [%thread] %m %n"/><!--日志輸出格式:%d{pattern}日期%m或者%msg為信息%M為method%L為行號%c類的完整名稱%thread線程名稱%n換行%-5level--><!-- 日志文件存放目錄 --><property name="log_dir" value="d:/logs"></property><!--控制臺輸出appender對象--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><!--輸出流對象 默認 System.out 改為 System.err--><target>System.err</target><!--日志格式配置--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--日志文件輸出appender對象--><appender name="file" class="ch.qos.logback.core.FileAppender"><!--日志格式配置--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--日志輸出路徑--><file>${log_dir}/logback.log</file></appender><!-- 生成html格式appender對象 --><appender name="htmlFile" class="ch.qos.logback.core.FileAppender"><!--日志格式配置--><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>%level%d{yyyy-MM-dd HH:mm:ss}%c%M%L%thread%m</pattern></layout></encoder><!--日志輸出路徑--><file>${log_dir}/logback.html</file></appender><!--RootLogger對象--><root level="all"><appender-ref ref="console"/><appender-ref ref="file"/><appender-ref ref="htmlFile"/></root> </configuration>RollingFileAppender配置
<?xml version="1.0" encoding="UTF-8"?> <configuration><!-- 自定義屬性 可以通過${name}進行引用--><property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c %M %L [%thread] %m %n"/><!--日志輸出格式:%d{pattern}日期%m或者%msg為信息%M為method%L為行號%c類的完整名稱%thread線程名稱%n換行%-5level--><!-- 日志文件存放目錄 --><property name="log_dir" value="d:/logs"></property><!--控制臺輸出appender對象--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><!--輸出流對象 默認 System.out 改為 System.err--><target>System.err</target><!--日志格式配置--><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 日志文件拆分和歸檔的appender對象--><appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志格式配置--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--日志輸出路徑--><file>${log_dir}/roll_logback.log</file><!--指定日志文件拆分和壓縮規則--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--通過指定壓縮文件名稱,來確定分割文件方式--><fileNamePattern>${log_dir}/rolling.%d{yyyy-MMdd}.log%i.gz</fileNamePattern><!--文件拆分大小--><maxFileSize>1MB</maxFileSize></rollingPolicy></appender><!--RootLogger對象--><root level="all"><appender-ref ref="console"/><appender-ref ref="rollFile"/></root> </configuration>自定義配置
<?xml version="1.0" encoding="UTF-8"?> <configuration><!-- 自定義屬性 可以通過${name}進行引用--><property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c %M %L [%thread] %m %n"/><!--日志輸出格式:%d{pattern}日期%m或者%msg為信息%M為method%L為行號%c類的完整名稱%thread線程名稱%n換行%-5level--><!-- 日志文件存放目錄 --><property name="log_dir" value="d:/logs/"></property><!--控制臺輸出appender對象--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><!--輸出流對象 默認 System.out 改為 System.err--><target>System.err</target><!--日志格式配置--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 日志文件拆分和歸檔的appender對象--><appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志格式配置--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--日志輸出路徑--><file>${log_dir}roll_logback.log</file><!--指定日志文件拆分和壓縮規則--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--通過指定壓縮文件名稱,來確定分割文件方式--><fileNamePattern>${log_dir}rolling.%d{yyyy-MMdd}.log%i.gz</fileNamePattern><!--文件拆分大小--><maxFileSize>1MB</maxFileSize></rollingPolicy><!--filter配置--><filter class="ch.qos.logback.classic.filter.LevelFilter"><!--設置攔截日志級別--><level>error</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--異步日志--><appender name="async" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="rollFile"/></appender><!--RootLogger對象--><root level="all"><appender-ref ref="console"/><appender-ref ref="async"/></root><!--自定義loggeradditivity表示是否從rootLogger繼承配置--><logger name="com.itfzk" level="debug" additivity="false"><appender-ref ref="console"/></logger> </configuration>六、log4j2
- 簡介
Apache Log4j2是對Log4j的升級版,參考了logback的一些優秀的設計,修復了一些問題,帶來了一些重大的提升
- 異常處理,在logback中,Appender中的異常不會被應用感知到,但是在log4j2中,提供了一些異常處理機制。
- 性能提升, log4j2相較于log4j 和logback都具有很明顯的性能提升,后面會有官方測試的數據。
自動重載配置,參考了logback的設計,當然會提供自動刷新參數配置,最實用的就是我們在生產 上可以動態的修改日志的級別而不需要重啟應用。
無垃圾機制,log4j2在大部分情況下,都可以使用其設計的一套無垃圾機制,避免頻繁的日志收集導致的jvm gc。 官網:
https://logging.apache.org/log4j/2.x/
- 引入依賴
- log4j2配置文件
- java程序
- 使用slf4j作為日志的門面,引入依賴
log4j2配置文件
<?xml version="1.0" encoding="UTF-8"?> <!--status="warn" 日志框架本身的輸出日志級別monitorInterval="5" 自動加載配置文件的間隔時間,不低于5秒 --> <Configuration status="warn" monitorInterval="5"><!--集中配置屬性進行管理使用時通過:${name}--><properties><property name="LOG_HOME">D:/logs</property></properties><!--日志處理--><Appenders><!--控制臺輸出--><Console name="Console" target="SYSTEM_OUT"><!--日志消息格式--><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/></Console><!--日志文件輸出--><File name="file" fileName="${LOG_HOME}/myfile.log"><!--日志消息格式--><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/></File><!--按照一定規則拆分的日志文件輸出--><RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"filePattern="/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyyMM-dd-HH-mm}-%i.log"><!--日志級別過濾器--><ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/><!--日志消息格式--><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/><Policies><!--系統啟動時,發出拆分規則,產生一個新的日志文件--><OnStartupTriggeringPolicy/><!--按照大小拆分--><SizeBasedTriggeringPolicy size="10 MB"/><!--按照時間拆分,規則按照 filePattern--><TimeBasedTriggeringPolicy/></Policies><!--在同一個目錄下,文件的個數限定為30個,超過按照時間覆蓋--><DefaultRolloverStrategy max="30"/></RollingFile><!--使用隨機讀寫流的日志文件輸出--><RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log"><!--日志消息格式--><PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/></RandomAccessFile></Appenders><!--loggers定義--><Loggers><!--使用 rootLogger 配置日志級別--><Root level="trace"><!--指定日志使用的處理器--><AppenderRef ref="Console"/><AppenderRef ref="file"/><AppenderRef ref="accessFile"/><AppenderRef ref="rollingFile"/></Root></Loggers> </Configuration>java程序
public class Log {//定義日志對象public final static Logger LOGGER = LoggerFactory.getLogger(Log.class);//打印日志信息@Testpublic void testLog(){LOGGER.error("error");LOGGER.warn("warn");LOGGER.info("info");LOGGER.debug("debug");LOGGER.trace("trace");} }-
異步日志:log4j2最大的特點就是異步日志,其性能的提升主要也是從異步日志中受益,我們來看看如何使用log4j2的異步日志。
-
同步日志示意圖
所謂同步日志:所謂同步日志,即當輸出日志時,必須等待日志輸出語句執行完畢后,才能執行后面的業務邏輯語句。
- 異步日志示意圖
異步日志的實現思路是在單獨的線程中執行I/O操作,在調用形如Logger.log的API時,能夠更快的返回到主程序中,以提高應用程序的性能。Log4j 2在異步日志領域,做了很多優化和改進。而我們只需要在配置文件中,做一個簡單的配置,就可以獲得異步日志記錄的功能特性。
Log4j 2設計了兩種異步日志:
- Async Appender。內部使用的一個隊列(ArrayBlockingQueue)和一個后臺線程,日志先存入隊列,后臺線程從隊列中取出日志。阻塞隊列容易受到鎖競爭的影響,當更多線程同時記錄時性能可能會變差。
- Async Logger。內部使用的是LMAX Disruptor技術,Disruptor是一個無鎖的線程間通信庫,它不是一個隊列,不需要排隊,從而產生更高的吞吐量和更低的延遲。
AsyncAppender的常用參數
- 混合異步
配置:com.itfzk日志是異步的,root日志是同步的
在 使用slf4j作為日志的門面 案例的基礎上使用
引入依賴
在加載log4j2.xml的啟動階段,如果檢測到配置了AsyncRoot或AsyncLogger,將啟動一個disruptor實例。
本文轉自
文章轉自
文章轉自
總結
以上是生活随笔為你收集整理的常用日志门面和日志实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Reference和ReferenceQ
- 下一篇: 互联网晚报 | 8月10日 星期二 |