天天看點

《我要進大廠系列 四》-談談你了解的日志架構

文章目錄

  • ​​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