文章目錄
- 1.為什麼需要日志架構
- 2.常見日志架構
- 2.1.日志架構介紹
- 2.2.市面上的日志架構
- 3.Slf4j使用
- 3.1.如何在系統中使用SLF4j
- 3.2.可能存在的問題
- 4.SpringBoot日志的預設配置
- 5.SpringBoot指定日志檔案
- 6.切換日志架構
1.為什麼需要日志架構
通過日志的方式記錄系統運作的過程或錯誤以便定位問題。
2.常見日志架構
2.1.日志架構介紹
對于我們日常開發日志是經常使用的,當然以前的我們可能還傻傻的各種
System.out.println("重要資料")
在控制台輸出各種重要資料呢,投入生産的時候再注釋掉。到現在為止呢,已經有很多日志可供選擇了,而市面上常見的日志架構有很多,比如:
JCL
、
SLF4J
、
Jboss-logging
、
jUL
、
log4j
、
log4j2
、
logback
等等,我們該如何選擇呢?
2.2.市面上的日志架構
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
日志的抽象層 | 日志實作 |
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging | Log4j JUL(java.util.logging) Log4j2 Logback |
左邊選一個抽象層、右邊來選一個實作;類似與我們經常使用的JDBC一樣,選擇不同的資料庫驅動。
下面我們先看看日志的抽象層:JCL大家應該很熟悉,Commons Logging,spring中常用的架構最後一次更新2014年~~~;jboss-logging使用的場景太少了;就剩下SLF4j了也是我們springboot中使用的日志抽象層。
日志實作:大家應該看着都很熟悉把Log4j大家應該用的挺多的,Logback是Log4j的更新版本出至于同一個人開發的,考慮到以後的更新使用等問題,又寫出了SLF4j的日志抽象層使用起來更加靈活。JUL(java.util.logging)一看就知道是java util包下的;Log4j2 咋一看像是Log4j的更新版本,其實并不是,它是apache下生産的日志架構。
SpringBoot底層是Spring架構, Spring架構預設使用JCL.
SpringBoot選用SLF4j和Logback
3.Slf4j使用
3.1.如何在系統中使用SLF4j
slf4j官網: https://www.slf4j.org
開發的時候,日志記錄方法的調用,不應該來直接調用日志的實作類,而是調用日志抽象層裡面的方法;
給系統裡面導入slf4j的jar和 logback的實作jar就可以。
使用示例:
package com.bruceliu.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
我們現在已經知道了springboot中使用的是 SLF4j和logback,但是如果我們想使用log4j該怎麼辦呢,從上面的圖示中我們可以看出想要使用log4j我們肯定還是要使用 SLF4j作為抽象層,但是中間給我們加入了一層适配層(Adaptation layer)然後使用log4j進行實作,那麼我們需要導入圖示中的jar包即可,其他的也是一樣了。是以說,以後開發的時候,日志記錄方法的調用,不應該來直接調用日志的實作類,而是調用日志抽象層裡面的方法; 每一個日志的實作架構都有自己的配置檔案。使用slf4j以後,配置檔案還是做成日志實作架構自己本身的配置檔案;
3.2.可能存在的問題
現在開發中我麼想使用slf4j+logback,但是對于一些遺留項目中例如Spring(commons-logging)、Hibernate(jboss-logging)…等等,如何去做到日志同一呢?
你想到的問題SLF4j能想不到嗎?答案是可以的,我們看看下面的圖就明白了
如何讓系統中所有的日志都統一到slf4j;
1、将系統中其他日志架構先排除出去;
2、用中間包來替換原有的日志架構;
3、我們導入slf4j其他的實作
其實通過idea我們建立一個springboot項目也可以檢視日志依賴(截取其中部分):
SpringBoot使用它來做日志功能:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
總結:
1)、SpringBoot底層也是使用slf4j+logback的方式進行日志記錄
2)、SpringBoot也把其他的架構的日志都替換成了slf4j;
3)、如果我們要引入其他架構?
SpringBoot能自動适配所有的日志,而且底層使用slf4j+logback的方式記錄日志,引入其他架構的時候,隻需要把這個架構依賴的日志架構排除掉即可
示例:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
4.SpringBoot日志的預設配置
SpringBoot日志的預設配置的位置:
package com.bruceliu;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot1ApplicationTests {
// 日志記錄器
private Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
// System.out.println();
// 日志的級别:由低到高
// trace<debug<info<warn<error
// 可以調整需要輸出的日志級别: 日志就隻會在這個級别及以後的進階别生效
logger.trace("這是trace日志...");
logger.debug("這是debug日志...");
// SpringBoot預設使用的是info級别的, 沒有指定級别的就使用SpringBoot預設規定的級别
logger.info("這是info日志...");
logger.warn("這是warn日志...");
logger.error("這是error日志...");
}
}
其他配置
設定日志的級别: logging.level
#修改日志的級别,預設root是info
logging.level.root=trace
指定日志的檔案名: logging.file ,會在目前項目下生成springboot.log日志
# 不指定路徑在目前項目下生成springboot.log日志
logging.file=springboot.log
# 可以指定完整的路徑;
logging.file=d://springboot.log
指定日志的檔案的目錄: logging.path , 日志檔案名稱使用SpringBoot預設的輸出日志檔案名.
# 在目前磁盤的根路徑下建立spring檔案夾和裡面的log檔案夾;使用spring.log 作為預設檔案
logging.path=/spring/log
如果同時指定了 logging.file , 則使用 logging.file , 不會使用 logging.path
指定日志在控制台輸出的格式: logging.pattern.console
# 在控制台輸出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
指定檔案中日志輸出的格式: logging.pattern.file
# 指定檔案中日志輸出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
日志的輸出格式
5.SpringBoot指定日志檔案
如果還是不夠用的話,可以自定義配置。給類路徑下放上每個日志架構自己的配置檔案即可;SpringBoot就不使用他預設配置的
logback.xml示例
logback.xml:直接就被日志架構識别了;
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jmxConfigurator />
<!-- 日志添加到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 滾動記錄檔案,先将日志記錄到指定檔案,當符合某個條件時,将日志記錄到其他檔案 -->
<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/quickstart.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/smt.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="businessLogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 按每小時滾動檔案,如果一個小時内達到10M也會滾動檔案, 滾動檔案将會壓縮成zip格式 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/smt-%d{yyyy-MM-dd_HH}.%i.zip</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 獨立的pattern -->
<encoder>
<pattern>%d{HH:mm:ss.SSS},%msg%n</pattern>
</encoder>
</appender>
<!-- project default level 本身沒有指定appender不列印 傳遞給上級root-->
<logger name="com.github.miemiedev.smt" level="DEBUG" />
<logger name="org.mybatis.spring.SqlSessionFactoryBean" level="DEBUG" />
<!--log4jdbc -->
<!-- <logger name="jdbc.sqltiming" level="INFO"/> -->
<root level="WARN">
<appender-ref ref="console" />
<appender-ref ref="rollingFile" />
</root>
</configuration>
logback-spring.xml:日志架構就不直接加載日志的配置項,由SpringBoot解析日志配置,可以使用SpringBoot 的進階Profile功能
<!-- 日志添加到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
</springProfile>
</layout>
</appender>
#指定目前模式
spring:
profiles:
active: dev
如果使用logback.xml作為日志配置檔案,還要使用profile功能,會有以下錯誤
no applicable action for [springProfile]
6.切換日志架構
棄用SpringBoot官方指定的logback日志架構,改用别的日志架構實作。但沒太大實際意義,因為logback是最先進的版本,一般沒有必要替換。(不推薦,隻是教大家如何切換)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
log4j.rootCategory=DEBUG, CONSOLE,LOGFILE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=-%p-%d{yyyy/MM/dd HH:mm:ss,SSS}-%l-%L-%m%n
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.File=mylog.log
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=-%p-%d{yyyy/MM/dd HH:mm:ss,SSS}-%l-%L-%m%n