java日志打印的完全使用指南
一、簡介
- 日志打印是java代碼開發(fā)中不可缺少的重要一步。
- 日志可以排查問題,可以搜集數(shù)據(jù)

二、常用日志框架
比較常用的日志框架就是logback, 一些老項(xiàng)目會使用log4j,他們用的都是slf4j-api統(tǒng)一接口。
(1) 使用log4j
log4j使用: 1. slf4j-api-1.5.11.jar 2. slf4j-log4j12-1.5.11.jar 3. log4j-1.2.15.jar 4. log4j.properties
代碼中
import org.slf4j.Logger; import org.slf4j.LoggerFactory; Logger logger = LoggerFactory.getLogger(xx.class);
(2) 使用logback
logback使用: 1. slf4j-api-1.5.11.jar 2. logback-core.jar 3. logback-classic.jar 4. logback.xml
代碼同log4j
import org.slf4j.Logger; import org.slf4j.LoggerFactory; Logger logger = LoggerFactory.getLogger(xx.class);
三、日志級別
TRACE < DEBUG < INFO < WARN < ERROR
日常使用較多的是error, info , debug
四、logback簡單介紹
簡單介紹下常用的logback,logback優(yōu)點(diǎn):
- 比log4j更快
- 和log4j使用了同一個(gè)接口,slf4j-api,可以非常方便切換
- 定義了功能非常豐富的appender
- 支持日志壓縮
logback要正確理解xml配置文件
- configuration:總的父節(jié)點(diǎn)
- property:自定義屬性
- appender:輸出控制器,可以輸出到控制臺,自定義文件等
- logger:日志級別
- root:控制器級別
一個(gè)例子:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<contextName>XXXXXXXX</contextName>
<property name="log.path" value="./log/"/>
<!-- 日志最大的歷史 30天 -->
<property name="maxHistory" value="30"/>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%-5level] [%logger{30}:%line] %msg%n"/>
<!--輸出到控制臺-->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是為開發(fā)使用,只配置最底級別,控制臺輸出的日志級別是大于或等于此級別的日志信息-->
<!--LevelFilter: 級別過濾器,根據(jù)日志級別進(jìn)行過濾。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志。-->
<!--例如:將過濾器的日志級別配置為INFO,所有INFO級別的日志交給appender處理,非INFO級別的日志,被過濾掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 臨界值過濾器,過濾掉低于指定臨界值的日志。當(dāng)日志級別等于或高于臨界值時(shí),過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時(shí),日志會被拒絕。-->
<!-- 過濾掉所有低于 DEBUG 級別的日志,留下DEBUG及以上級別的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 時(shí)間滾動輸出 level為 INFO 日志 -->
<appender name="errorFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 級別過濾器,根據(jù)日志級別進(jìn)行過濾。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志。-->
<!--例如:將過濾器的日志級別配置為INFO,所有INFO級別的日志交給appender處理,非INFO級別的日志,被過濾掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 臨界值過濾器,過濾掉低于指定臨界值的日志。當(dāng)日志級別等于或高于臨界值時(shí),過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時(shí),日志會被拒絕。-->
<!-- 過濾掉所有低于 DEBUG 級別的日志,留下DEBUG及以上級別的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/error.log</file>
<!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志歸檔路徑以及格式 -->
<fileNamePattern>${log.path}/error-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天數(shù)-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志總保存量為2GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件達(dá)到 最大100MB時(shí)會被壓縮和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 時(shí)間滾動輸出 level為 INFO 日志 -->
<appender name="infoFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 級別過濾器,根據(jù)日志級別進(jìn)行過濾。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志。-->
<!--例如:將過濾器的日志級別配置為INFO,所有INFO級別的日志交給appender處理,非INFO級別的日志,被過濾掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 臨界值過濾器,過濾掉低于指定臨界值的日志。當(dāng)日志級別等于或高于臨界值時(shí),過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時(shí),日志會被拒絕。-->
<!-- 過濾掉所有低于 DEBUG 級別的日志,留下DEBUG及以上級別的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/info.log</file>
<!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志歸檔路徑以及格式 -->
<fileNamePattern>${log.path}/info-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天數(shù)-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志總保存量為10GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件達(dá)到 最大100MB時(shí)會被壓縮和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 時(shí)間滾動輸出 level為 INFO 日志 -->
<appender name="debugFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 級別過濾器,根據(jù)日志級別進(jìn)行過濾。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志。-->
<!--例如:將過濾器的日志級別配置為INFO,所有INFO級別的日志交給appender處理,非INFO級別的日志,被過濾掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 臨界值過濾器,過濾掉低于指定臨界值的日志。當(dāng)日志級別等于或高于臨界值時(shí),過濾器返回NEUTRAL;當(dāng)日志級別低于臨界值時(shí),日志會被拒絕。-->
<!-- 過濾掉所有低于 DEBUG 級別的日志,留下DEBUG及以上級別的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/debug.log</file>
<!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志歸檔路徑以及格式 -->
<fileNamePattern>${log.path}/debug-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天數(shù)-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志總保存量為2GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件達(dá)到 最大100MB時(shí)會被壓縮和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<logger name="com.baomidou" level="debug"/>
<root level="info">
<appender-ref ref="consoleAppender"/>
<appender-ref ref="errorFileAppender"/>
<appender-ref ref="infoFileAppender"/>
<appender-ref ref="debugFileAppender"/>
</root>
</configuration>
五、常見問題
- 1、日志打的少,不好排查問題?
我們經(jīng)常會遇到一個(gè)生產(chǎn)問題,去看日志,啥都沒有,只能重新加日志,發(fā)包,再排查問題;
所以我們要養(yǎng)成打日志的習(xí)慣,開發(fā)環(huán)境可以debug看,生產(chǎn)看不了,只能加日志,在開發(fā)的時(shí)候就把必要的日志加上;
比較重要的是接口的入?yún)?,返回,重要?jié)點(diǎn)開始,結(jié)束,mq發(fā)送接收等。
- 2、error, info , debug分別都什么時(shí)候使用?
error: 捕獲異常的時(shí)候使用,這個(gè)沒有異議
info: 比較重要的信息,使用頻次不是非常高的場景,比如入?yún)⒊鰠?br />debug: 一個(gè)是不是特別重要的信息,但是又不能少,還有數(shù)據(jù)量大的數(shù)據(jù),比如大量mq信息,訪問頻繁的接口入?yún)⒊鰠?/p>
- 3、開啟debug好多無用的debug信息怎么辦?
把項(xiàng)目的目錄定為debug,其它定成info。這樣只有本項(xiàng)目的debug日志會打印了
logging.level.root=info
logging.level.cn.mypackage=debug
- 4、需要自定義日志文件嗎?
logback可以把日志寫進(jìn)自定義文件,debug,info,error分開存儲,歷史數(shù)據(jù)還能壓縮;
按自己項(xiàng)目的需求來,大型項(xiàng)目建議分開存儲。
- 5、springboot啟動命令自帶的日志和自定義日志文件的日志重復(fù)怎么辦?
我們一般啟動springboot項(xiàng)目命令為:nohup java -jar XXXXXXXX.jar >> XXXXXXX.log 2>&1 &
這個(gè)會生成一個(gè)日志文件,logback配置也會生成自己的日志文件,就會重復(fù),造成空間浪費(fèi),如何取舍?如果你們公司統(tǒng)一打包腳本的話,就用命令生成的日志文件吧,把logback配置去掉;
如果你們公司自由度比較高,就用logback生成的日志,把命令改成 >/dev/null 就可以了
- 6、debug日志正確寫法?
有些人可能打debug日志直接logger.debug("****");
如果項(xiàng)目的日志級別比較高,就比較浪費(fèi)性能,可以加一個(gè)
if (log.isDebugEnabled()) {
log.debug("XXXXXXXXXXXXX");
}
- 7、動態(tài)日志級別?
有些公司支持動態(tài)配置文件,比如diamond,nacos等,可以修改配置文件的級別,動態(tài)生效 logging.level.root=info #logging.level.root=debug 日常開在info,出了問題開debug找,資源有限可以這樣做,不推薦生產(chǎn)使用
總結(jié)
到此這篇關(guān)于java日志打印的文章就介紹到這了,更多相關(guān)java日志打印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決springboot運(yùn)行出現(xiàn)錯誤:找不到或無法加載主類com.xxxx.xxxx.Application問題
文章介紹了在服務(wù)器上運(yùn)行一個(gè)未使用的Java項(xiàng)目時(shí)遇到的“找不到或無法加載主類”錯誤,并提供了兩種解決方法:通過Maven install或build …、Goals輸入install并跳過測試來重新構(gòu)建項(xiàng)目2024-11-11
Mybatis實(shí)現(xiàn)分頁的注意點(diǎn)
Mybatis提供了強(qiáng)大的分頁攔截實(shí)現(xiàn),可以完美的實(shí)現(xiàn)分功能。下面小編給大家分享小編在使用攔截器給mybatis進(jìn)行分頁所遇到的問題及注意點(diǎn),需要的朋友一起看看吧2017-07-07
Java之Scanner.nextLine()讀取回車的問題及解決
這篇文章主要介紹了Java之Scanner.nextLine()讀取回車的問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
idea springboot遠(yuǎn)程debug的操作方法
這篇文章主要介紹了idea springboot遠(yuǎn)程debug的操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
java設(shè)計(jì)模式之實(shí)現(xiàn)對象池模式示例分享
對象池模式經(jīng)常用在頻繁創(chuàng)建、銷毀對象(并且對象創(chuàng)建、銷毀開銷很大)的場景,比如數(shù)據(jù)庫連接池、線程池、任務(wù)隊(duì)列池等。本代碼簡單,沒有限制對象池大小2014-02-02
MyBatis+Calcite實(shí)現(xiàn)多數(shù)據(jù)庫SQL自動適配的詳細(xì)指南
在當(dāng)今企業(yè)IT環(huán)境中,數(shù)據(jù)庫異構(gòu)性已成為常態(tài),根據(jù)DB-Engines最新調(diào)研,超過78%的企業(yè)同時(shí)使用兩種以上數(shù)據(jù)庫系統(tǒng),所以本文就來為大家介紹一下如何基于MyBatis+Calcite實(shí)現(xiàn)多數(shù)據(jù)庫SQL自動適配吧2025-04-04

