Logback是log4j框架的作者開發(fā)的新一代日志框架,它效率更高赁豆、能夠適應(yīng)諸多的運(yùn)行環(huán)境,同時天然支持SLF4J冗美。
默認(rèn)情況下魔种,Spring Boot會用Logback來記錄日志,并用INFO級別輸出到控制臺粉洼。在運(yùn)行應(yīng)用程序和其他例子時节预,你應(yīng)該已經(jīng)看到很多INFO級別的日志了叶摄。
從上圖可以看到,日志輸出內(nèi)容元素具體如下:
- 時間日期:精確到毫秒
- 日志級別:ERROR, WARN, INFO, DEBUG or TRACE
- 進(jìn)程ID
- 分隔符:
---
標(biāo)識實(shí)際日志的開始 - 線程名:方括號括起來(可能會截?cái)嗫刂婆_輸出)
- Logger名:通常使用源代碼的類名
- 日志內(nèi)容
添加日志依賴
假如maven依賴中添加了spring-boot-starter-logging:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
那么安拟,我們的Spring Boot應(yīng)用將自動使用logback作為應(yīng)用日志框架蛤吓,Spring Boot啟動的時候,由org.springframework.boot.logging.Logging-Application-Listener
根據(jù)情況初始化并使用糠赦。
但是呢会傲,實(shí)際開發(fā)中我們不需要直接添加該依賴,你會發(fā)現(xiàn)spring-boot-starter其中包含了 spring-boot-starter-logging拙泽,該依賴內(nèi)容就是 Spring Boot 默認(rèn)的日志框架 logback淌山。而博主這次項(xiàng)目的例子是基于上一篇的,工程中有用到了Thymeleaf顾瞻,而Thymeleaf依賴包含了spring-boot-starter泼疑,最終我只要引入Thymeleaf即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
默認(rèn)配置屬性支持
Spring Boot為我們提供了很多默認(rèn)的日志配置荷荤,所以退渗,只要將spring-boot-starter-logging作為依賴加入到當(dāng)前應(yīng)用的classpath,則“開箱即用”蕴纳。
下面介紹幾種在application.properties就可以配置的日志相關(guān)屬性会油。
控制臺輸出
日志級別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設(shè)置為WARN袱蚓,則低于WARN的信息都不會輸出钞啸。
Spring Boot中默認(rèn)配置ERROR
、WARN
和INFO
級別的日志輸出到控制臺喇潘。您還可以通過啟動您的應(yīng)用程序–debug標(biāo)志來啟用“調(diào)試”模式(開發(fā)的時候推薦開啟),以下兩種方式皆可:
- 在運(yùn)行命令后加入
--debug
標(biāo)志体斩,如:$ java -jar springTest.jar --debug
- 在
application.properties
中配置debug=true
,該屬性置為true的時候颖低,核心Logger(包含嵌入式容器絮吵、hibernate、spring)會輸出更多內(nèi)容忱屑,但是你自己應(yīng)用的日志并不會輸出為DEBUG級別蹬敲。
文件輸出
默認(rèn)情況下,Spring Boot將日志輸出到控制臺莺戒,不會寫到日志文件伴嗡。如果要編寫除控制臺輸出之外的日志文件,則需在application.properties中設(shè)置logging.file或logging.path屬性从铲。
- logging.file瘪校,設(shè)置文件,可以是絕對路徑,也可以是相對路徑阱扬。如:
logging.file=my.log
- logging.path泣懊,設(shè)置目錄,會在該目錄下創(chuàng)建spring.log文件麻惶,并寫入日志內(nèi)容馍刮,如:
logging.path=/var/log
如果只配置 logging.file,會在項(xiàng)目的當(dāng)前路徑下生成一個 xxx.log 日志文件窃蹋。
如果只配置 logging.path卡啰,在 /var/log文件夾生成一個日志文件為 spring.log
注:二者不能同時使用,如若同時使用脐彩,則只有l(wèi)ogging.file生效
默認(rèn)情況下碎乃,日志文件的大小達(dá)到10MB時會切分一次,產(chǎn)生新的日志文件惠奸,默認(rèn)級別為:ERROR、WARN恰梢、INFO
級別控制
所有支持的日志記錄系統(tǒng)都可以在Spring環(huán)境中設(shè)置記錄級別(例如在application.properties中)
格式為:’logging.level.* = LEVEL’
-
logging.level
:日志級別控制前綴佛南,*
為包名或Logger名 -
LEVEL
:選項(xiàng)TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
舉例:
-
logging.level.com.dudu=DEBUG
:com.dudu
包下所有class以DEBUG級別輸出 -
logging.level.root=WARN
:root日志以WARN級別輸出
自定義日志配置
由于日志服務(wù)一般都在ApplicationContext創(chuàng)建前就初始化了,它并不是必須通過Spring的配置文件控制嵌言。因此通過系統(tǒng)屬性和傳統(tǒng)的Spring Boot外部配置文件依然可以很好的支持日志控制和管理嗅回。
根據(jù)不同的日志系統(tǒng),你可以按如下規(guī)則組織配置文件名摧茴,就能被正確加載:
- Logback:
logback-spring.xml
,logback-spring.groovy
,logback.xml
,logback.groovy
- Log4j:
log4j-spring.properties
,log4j-spring.xml
,log4j.properties
,log4j.xml
- Log4j2:
log4j2-spring.xml
,log4j2.xml
- JDK (Java Util Logging):
logging.properties
Spring Boot官方推薦優(yōu)先使用帶有-spring
的文件名作為你的日志配置(如使用logback-spring.xml
绵载,而不是logback.xml
),命名為logback-spring.xml的日志配置文件苛白,spring boot可以為它添加一些spring boot特有的配置項(xiàng)(下面會提到)娃豹。
上面是默認(rèn)的命名規(guī)則,并且放在src/main/resources
下面即可购裙。
如果你即想完全掌控日志配置懂版,但又不想用logback.xml
作為Logback
配置的名字,可以在application.properties
配置文件里面通過logging.config屬性指定自定義的名字:
雖然一般并不需要改變配置文件的名字躏率,但是如果你想針對不同運(yùn)行時Profile使用不同的日
志配置躯畴,這個功能會很有用。
下面我們來看看一個普通的logback-spring.xml例子
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<property name="log.path" value="/Users/tengjun/Documents/log" />
<!--輸出到控制臺-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--輸出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logback為java中的包 -->
<logger name="com.dudu.controller"/>
<!--logback.LogbackDemo:類的全路徑 -->
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
根節(jié)點(diǎn)<configuration>
包含的屬性
- scan:當(dāng)此屬性設(shè)置為true時薇芝,配置文件如果發(fā)生改變蓬抄,將會被重新加載,默認(rèn)值為true夯到。
- scanPeriod:設(shè)置監(jiān)測配置文件是否有修改的時間間隔嚷缭,如果沒有給出時間單位,默認(rèn)單位是毫秒黄娘。當(dāng)scan為true時峭状,此屬性生效克滴。默認(rèn)的時間間隔為1分鐘。
- debug:當(dāng)此屬性設(shè)置為true時优床,將打印出logback內(nèi)部日志信息劝赔,實(shí)時查看logback運(yùn)行狀態(tài)。默認(rèn)值為false胆敞。
根節(jié)點(diǎn)<configuration>
的子節(jié)點(diǎn):
<configuration>
下面一共有2個屬性着帽,3個子節(jié)點(diǎn),分別是:
屬性一:設(shè)置上下文名稱<contextName>
每個logger都關(guān)聯(lián)到logger上下文移层,默認(rèn)上下文名稱為“default”仍翰。但可以使用<contextname>設(shè)置成其他名字,用于區(qū)分不同應(yīng)用程序的記錄观话。一旦設(shè)置予借,不能修改,可以通過%contextName來打印日志上下文名稱。
<contextName>logback</contextName>
屬性二:設(shè)置變量<property>
用來定義變量值的標(biāo)簽频蛔,<property>有兩個屬性灵迫,name和value;其中name的值是變量的名稱晦溪,value的值時變量定義的值瀑粥。通過<property>定義的值會被插入到logger上下文中。定義變量后三圆,可以使“${}”來使用變量狞换。</property></property>
<property name="log.path" value="/Users/tengjun/Documents/log" />
子節(jié)點(diǎn)一<appender>
appender用來格式化日志輸出節(jié)點(diǎn),有倆個屬性name和class舟肉,class用來指定哪種輸出策略修噪,常用就是控制臺輸出策略和文件輸出策略。
控制臺輸出ConsoleAppender:
<!--輸出到控制臺-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<encoder>
表示對日志進(jìn)行編碼:
-
%d{HH: mm:ss.SSS}
——日志輸出時間 -
%thread
——輸出日志的進(jìn)程名字度气,這在Web應(yīng)用以及異步任務(wù)處理中很有用 -
%-5level
——日志級別割按,并且使用5個字符靠左對齊 -
%logger{36}
——日志輸出者的名字 -
%msg
——日志消息 -
%n
——平臺的換行符
ThresholdFilter為系統(tǒng)定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR級別以下的日志不輸出到文件中磷籍。如果不用記得注釋掉适荣,不然你控制臺會發(fā)現(xiàn)沒日志~
輸出到文件RollingFileAppender
另一種常見的日志輸出到文件,隨著應(yīng)用的運(yùn)行時間越來越長院领,日志也會增長的越來越多弛矛,將他們輸出到同一個文件并非一個好辦法。RollingFileAppender
用于切分文件日志:
<!--輸出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
其中重要的是rollingPolicy
的定義比然,上例中<fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
定義了日志的切分方式——把每一天的日志歸檔到一個文件中丈氓,<maxHistory>30</maxHistory>
表示只保留最近30天的日志,以防止日志填滿整個磁盤空間。同理万俗,可以使用%d{yyyy-MM-dd_HH-mm}
來定義精確到分的日志切分方式湾笛。<totalSizeCap>1GB</totalSizeCap>
用來指定日志文件的上限大小,例如設(shè)置為1GB的話闰歪,那么到了這個值嚎研,就會刪除舊的日志。
補(bǔ):如果你想把日志直接放到當(dāng)前項(xiàng)目下库倘,把${log.path}/
去掉即可临扮。
logback 每天生成和大小生成沖突的問題可以看這個解答:傳送門
子節(jié)點(diǎn)二<root>
root節(jié)點(diǎn)是必選節(jié)點(diǎn),用來指定最基礎(chǔ)的日志輸出級別教翩,只有一個level屬性杆勇。
- level:用來設(shè)置打印級別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF饱亿,不能設(shè)置為INHERITED或者同義詞NULL蚜退。
默認(rèn)是DEBUG。
<root>可以包含零個或多個<appender-ref>元素彪笼,標(biāo)識這個appender將會添加到這個logger关霸。
<root level="debug">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
子節(jié)點(diǎn)三<logger>
<logger>
用來設(shè)置某一個包或者具體的某一個類的日志打印級別、以及指定<appender>
杰扫。<logger>
僅有一個name屬性,一個可選的level和一個可選的addtivity屬性膘掰。
-
name
:用來指定受此logger約束的某一個包或者具體的某一個類章姓。 -
level
:用來設(shè)置打印級別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF识埋,還有一個特俗值INHERITED或者同義詞NULL凡伊,代表強(qiáng)制執(zhí)行上級的級別。如果未設(shè)置此屬性窒舟,那么當(dāng)前l(fā)ogger將會繼承上級的級別系忙。 -
addtivity
:是否向上級logger傳遞打印信息。默認(rèn)是true惠豺。
logger在實(shí)際使用的時候有兩種情況
先來看一看代碼中如何使用
package com.dudu.controller;
@Controller
public class LearnController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public Map<String,Object> login(HttpServletRequest request, HttpServletResponse response){
//日志級別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL银还,如果設(shè)置為WARN,則低于WARN的信息都不會輸出洁墙。
logger.trace("日志輸出 trace");
logger.debug("日志輸出 debug");
logger.info("日志輸出 info");
logger.warn("日志輸出 warn");
logger.error("日志輸出 error");
Map<String,Object> map =new HashMap<String,Object>();
String userName=request.getParameter("userName");
String password=request.getParameter("password");
if(!userName.equals("") && password!=""){
User user =new User(userName,password);
request.getSession().setAttribute("user",user);
map.put("result","1");
}else{
map.put("result","0");
}
return map;
}
}
這是一個登錄的判斷的方法蛹疯,我們引入日志,并且打印不同級別的日志热监,然后根據(jù)logback-spring.xml中的配置來看看打印了哪幾種級別日志捺弦。
第一種:帶有l(wèi)ogger的配置,不指定級別,不指定appender
<logger name="com.dudu.controller"/>
<logger name="com.dudu.controller" />
將控制controller包下的所有類的日志的打印列吼,但是并沒用設(shè)置打印級別幽崩,所以繼承他的上級<root>的日志級別“info”;
沒有設(shè)置addtivity寞钥,默認(rèn)為true慌申,將此logger的打印信息向上級傳遞;
沒有設(shè)置appender凑耻,此logger本身不打印任何信息太示。
<root level="info">
將root的打印級別設(shè)置為“info”,指定了名字為“console”的appender香浩。</root>
當(dāng)執(zhí)行com.dudu.controller.LearnController類的login方法時类缤,LearnController 在包c(diǎn)om.dudu.controller中,所以首先執(zhí)行<logger name="com.dudu.controller"/>
邻吭,將級別為“info”及大于“info”的日志信息傳遞給root餐弱,本身并不打印囱晴;
root接到下級傳遞的信息膏蚓,交給已經(jīng)配置好的名為“console”的appender處理,“console”appender將信息打印到控制臺畸写;
打印結(jié)果如下:
16:00:17.407 logback [http-nio-8080-exec-8] INFO com.dudu.controller.LearnController - 日志輸出 info
16:00:17.408 logback [http-nio-8080-exec-8] WARN com.dudu.controller.LearnController - 日志輸出 warn
16:00:17.408 logback [http-nio-8080-exec-8] ERROR com.dudu.controller.LearnController - 日志輸出 error
第二種:帶有多個logger的配置驮瞧,指定級別,指定appender
<!--logback.LogbackDemo:類的全路徑 -->
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
控制com.dudu.controller.LearnController
類的日志打印枯芬,打印級別為“WARN”;
additivity屬性為false论笔,表示此logger的打印信息不再向上級傳遞;
指定了名字為“console”的appender;
這時候執(zhí)行com.dudu.controller.LearnController類的login方法時,先執(zhí)行<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
,
將級別為“WARN”及大于“WARN”的日志信息交給此logger指定的名為“console”的appender處理千所,在控制臺中打出日志狂魔,不再向上級root傳遞打印信息。
打印結(jié)果如下:
16:00:17.408 logback [http-nio-8080-exec-8] WARN com.dudu.controller.LearnController - 日志輸出 warn
16:00:17.408 logback [http-nio-8080-exec-8] ERROR com.dudu.controller.LearnController - 日志輸出 error
當(dāng)然如果你把a(bǔ)dditivity=”false”改成additivity=”true”的話淫痰,就會打印兩次最楷,因?yàn)榇蛴⌒畔⑾蛏霞墏鬟f,logger本身打印一次待错,root接到后又打印一次籽孙。
注:使用mybatis的時候,sql語句是debug下才會打印朗鸠,而這里我們只配置了info蚯撩,所以想要查看sql語句的話,有以下兩種操作:
- 第一種把
<root level="info">
改成<root level="DEBUG">
這樣就會打印sql烛占,不過這樣日志那邊會出現(xiàn)很多其他消息胎挎。 - 第二種就是單獨(dú)給dao下目錄配置debug模式沟启,代碼如下,這樣配置sql語句會打印犹菇,其他還是正常info級別:
<logger name="com.dudu.dao" level="DEBUG" additivity="false">
<appender-ref ref="console" />
</logger>
多環(huán)境日志輸出
據(jù)不同環(huán)境(prod:生產(chǎn)環(huán)境德迹,test:測試環(huán)境,dev:開發(fā)環(huán)境)來定義不同的日志輸出揭芍,在 logback-spring.xml中使用 springProfile 節(jié)點(diǎn)來定義胳搞,方法如下:
文件名稱不是logback.xml,想使用spring擴(kuò)展profile支持称杨,要以logback-spring.xml命名
<!-- 測試環(huán)境+開發(fā)環(huán)境. 多個使用逗號隔開. -->
<springProfile name="test,dev">
<logger name="com.dudu.controller" level="info" />
</springProfile>
<!-- 生產(chǎn)環(huán)境. -->
<springProfile name="prod">
<logger name="com.dudu.controller" level="ERROR" />
</springProfile>
可以啟動服務(wù)的時候指定 profile (如不指定使用默認(rèn))肌毅,如指定prod 的方式為:
java -jar xxx.jar –spring.profiles.active=prod
到此為止終于介紹完日志框架了,平時使用的時候推薦用自定義logback-spring.xml來配置姑原,代碼中使用日志也很簡單悬而,類里面添加private Logger logger = LoggerFactory.getLogger(this.getClass());
即可。
轉(zhuǎn)自: http://tengj.top/2017/04/05/springboot7/