集成日誌框架實踐

一、日誌概述

1. 日誌的級別

Java應用中,日誌一般分爲以下5個級別:

  • ERROR 錯誤信息
  • WARN 警告信息
  • INFO 一般信息
  • DEBUG 調試信息
  • TRACE 跟蹤信息

Spring Boot使用Apache的Commons Logging作爲內部的日誌框架,其僅僅是一個日誌接口,在實際應用中需要爲該接口來指定相應的日誌實現。Spring Boot默認的日誌實現是Java Util Logging,是JDK自帶的日誌包,此外Spring Boot當然也支持Log4J、Logback這類很流行的日誌框架。

2. 日誌框架的作用

日誌框架能控制什麼?需要打印的日誌都能滿足什麼樣的需求?

1、能夠控制日誌信息想往哪裏打就往哪裏打,比如:控制檯、文件、郵箱、數據庫等等;
2、能夠控制日誌信息想怎麼打就怎麼打,比如:想要打印時間、程序的名稱、程序的方法名、程序的行號、線程的名稱等等;
3、能夠控制日誌信息想打什麼打什麼,不想打的就不打,日誌信息是分級別的,有時候只想看錯誤的信息或者警告的信息,有時候想看到所有的信息調試程序等等。

記錄日誌信息的作用:

  • 監視代碼中變量的變化情況,週期性的記錄到文件中供其它應用進行統計分析;
  • 跟蹤代碼運行時軌跡,作爲日後審計的依據;
  • 擔當集成開發環境中的調試器的作用,向文件或控制檯打印代碼的調試信息。

二、Spring Boot使用日誌

使用slf4j-api接口,Java Util Logging作爲默認的日誌實現

1. 設置level爲INFO

application.properties配置:

logging.level.root=INFO

控制器代碼如下:

package com.example.loggingdemo.controller;

import com.example.loggingdemo.LoggingdemoApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/logging")
public class TestLogging {

    private static Logger logger = LoggerFactory.getLogger(LoggingdemoApplication.class);

    @GetMapping("/hello")
    public String sayHello() {
        logger.info("say hello...");
        return "hello";
    }
}

運行結果(由於將日誌等級設置爲INFO,因此包含INFO及以上級別的日誌信息都會打印出來):
logging level全設置爲info
圖片可以看出,很多大部分的INFO日誌均來自於Spring Boot框架本身,如果我們想屏蔽它們,可以將日誌級別統一先全部設置爲ERROR,這樣框架自身的INFO信息不會被打印。然後再將應用中特定的包設置爲DEBUG級別的日誌,這樣就可以只看到所關心的包中的DEBUG及以上級別的日誌了。


2. 控制特定包的日誌級別

application.properties配置:

logging.level.root=error
logging.level.com.example.loggingdemo.controller:debug

將root日誌級別設置爲ERROR,然後再將com.example.loggingdemo.controller包的日誌級別設爲DEBUG,即先禁止所有再允許個別包的設置方法。

控制器部分代碼:

private Logger logger = LoggerFactory.getLogger(this.getClass());

運行結果:
logging level設置特定包
可見框架自身的INFO級別日誌全部藏匿,而指定包中的日誌按級別順利打印。


3. 將日誌輸出到某個文件中

application.properties配置:

logging.file=E:/logs/hello.log

運行結果:
日誌輸出到本地某個文件夾下
使用Spring Boot Logging日誌框架,發現雖然日誌文件已生成並輸出,但控制檯中依舊會打印日誌,使用Spring Boot Logging無法解決這個問題。


三、Spring Boot集成Log4J2日誌框架

1. pom.xml中添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
	    <exclusion>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-logging</artifactId>
	    </exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

2. 在resources目錄下新建log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appenders>
        <File name="file" fileName="E:/logs/hello2.log">
            <PatternLayout pattern="%d{HH:mm:ss,SSS} %p %c (%L) - %m%n"/>
        </File>
    </appenders>
    <loggers>
        <root level="ERROR">
            <appender-ref ref="file"/>
        </root>
        <logger name="com.example.loggingdemo.controller" level="DEBUG"/>
    </loggers>
</configuration>

3. 控制器代碼

package com.example.loggingdemo.controller;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/logging")
public class TestLogging {

    private final Logger logger = LogManager.getLogger(this.getClass());

    @GetMapping("/hello")
    public String sayHello() {

        for (int i = 0; i < 1000; i++) {
            logger.info("info execute index method");
            logger.warn("warn execute index method");
            logger.error("error execute index method");
        }
        return "say hello";
    }
}

運行結果:
使用log4j2控制檯沒有輸出
運行程序發現控制檯沒有日誌輸出,而hello2.log文件中有內容,即符合我們的要求。


四、Log4J詳細配置

1. log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="warn">

    <properties>
        <Property name="app_name">springboot-web</Property>
        <Property name="log_path">logs/${app_name}</Property>
    </properties>

    <appenders>
        <console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%d][%t][%p][%l] %m%n"/>
        </console>

        <RollingFile name="RollingFileInfo" fileName="${log_path}/info.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO"/>
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
            <Policies>
                <!-- 歸檔每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制單個文件大小 -->
                <SizeBasedTriggeringPolicy size="2 MB"/>
            </Policies>
            <!-- 限制每天文件個數 -->
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>

        <RollingFile name="RollingFileWarn" fileName="${log_path}/warn.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="WARN"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
            <Policies>
                <!-- 歸檔每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制單個文件大小 -->
                <SizeBasedTriggeringPolicy size="2 MB"/>
            </Policies>
            <!-- 限制每天文件個數 -->
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>

        <RollingFile name="RollingFileError" fileName="${log_path}/error.log"
                     filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="ERROR"/>
            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
            <Policies>
                <!-- 歸檔每天的文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 限制單個文件大小 -->
                <SizeBasedTriggeringPolicy size="2 MB"/>
            </Policies>
            <!-- 限制每天文件個數 -->
            <DefaultRolloverStrategy compressionLevel="0" max="10"/>
        </RollingFile>
    </appenders>

    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
    </loggers>
</configuration>

控制器及其他代碼不變,運行結果如下:
日誌文件輸出到本地項目目錄下
日誌會根據不同的級別存儲在不同的文件,當日志文件大小超過2M以後會分多個文件壓縮存儲,生產環境的日誌文件大小建議調整爲20-50MB。

2. SSM框架下Log4j配置(補充)

  • 控制器代碼
private static Logger logger = Logger.getLogger(Test.class);  
	 
    public static void main(String[] args) {  
 
        // 記錄debug級別的信息  
        logger.debug("This is debug message.");  
        // 記錄info級別的信息  
        logger.info("This is info message.");  
        // 記錄error級別的信息  
        logger.error("This is error message.");  
    }
}
  • Log4j.properties
### org.apache.log4j.ConsoleAppender (控制檯)
### org.apache.log4j.FileAppender (文件) 
### org.apache.log4j.DailyRollingFileAppender (每天產生一個日誌文件)
### org.apache.log4j.RollingFileAppender (文件大小到達指定尺寸的時候產生一個新的文件) 
### org.apache.log4j.WriterAppender (將日誌信息以流格式發送到任意指定的地方)

### ERROR、WARN、INFO、DEBUG 優先級從高到低 
### 設置日誌輸出的等級爲DEBUG,低於DEBUG不會輸出
### 設置輸出到控制檯 (stdout)、D、E 三個地方 
log4j.rootLogger = debug,stdout,D,E

### 輸出信息到控制擡 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 輸出DEBUG 級別以上的日誌到=E://logs/error.log ###
### 第二個地方D, 以滾動的方式輸出到文件,文件名是log.log
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 輸出ERROR 級別以上的日誌到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章