SpringBoot不重啓修改日誌級別【Slf4jj動態日誌級別】

SpringBoot不重啓修改日誌級別【Slf4jj動態日誌級別】

前言

需求: 線上日誌級別高,而定位問題時需要低級別日誌便於分析問題

功能:不重啓服務器,提供設置頁,手動觸發Slf4j 項目日誌級別變化

擴展:可將此功能放入後臺管理系統中,管理員只需,點選日誌級別即可切換服務器的日誌級別。

栗子 Like this:

在這裏插入圖片描述
或者使用命令行

curl 項目訪問地址/sys/log/level/error
curl 項目訪問地址/sys/log/level/warn
curl 項目訪問地址/sys/log/level/info
curl 項目訪問地址/sys/log/level/debug
curl 項目訪問地址/sys/log/level/trace

查看日誌狀態

在這裏插入圖片描述

懶人如何實現?請copy如下代碼 - _ -

Controller.java

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.Objects;

/**
 * @ IDE    :IntelliJ IDEA.
 * @ Date   :2019/11/6  19:40
 * @ Desc   :動態修改系統日誌等級。
 */
@Slf4j
@RestController
@RequestMapping("/sys/log/level")
public class SysLogLevelController {
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

    /**
     * 測試當前日誌等級接口
     * @param packageName           包名
     * @return Result               返回結果
     * 栗子:
     *  curl [baseUrl]/sys/log/level/test
     */
    @GetMapping("/test")
    public Result testLevel(String packageName){
        log.trace("trace");
        log.debug("debug");
        log.info("info");
        log.warn("warn");
        log.error("error");

        StringBuilder msg = new StringBuilder();
        //全局日誌等級 + 項目日誌等級 + 具體包的日誌等級
        msg.append(getLogger("root"));
        msg.append(getLogger(【SpringBoot啓動類】.class.getPackage().getName()));
        if (packageName!=null && !packageName.isEmpty()){
            msg.append(getLogger(packageName));
        }
        return Result.getMsgResult(msg.toString());
    }

    /**
     * 修改日誌級別接口
     * @param level                 日誌級別
     * @return Result               返回結果
     * 栗子:
     *  curl [baseUrl]/sys/log/level/info/[包名]
     *  curl [baseUrl]/sys/log/level/debug/[包名]
     */
    @GetMapping("/{level}/{packageName}")
    public Result changeLevel(@PathVariable String level,@PathVariable String packageName) {
        return Result.getMsgResult(setLogger(packageName,level));
    }

    /**
     * 修改日誌級別接口
     * @param level                 日誌級別
     * @return Result               返回結果
     * 栗子:
     *  curl [baseUrl]/sys/log/level/info
     *  curl [baseUrl]/sys/log/level/debug
     */
    @GetMapping("/{level}")
    public Result changeLevel(@PathVariable String level) {
        return Result.getMsgResult(setLogger("root",level));
    }


    /**
     * 獲取指定包日誌級別             封裝[設置日誌級別+封裝返回值信息]
     * @param packageName           包名
     * @return String               日誌級別信息
     */
    private String getLogger(String packageName){
        return  packageName + "日誌等級爲:" + getLevel(packageName);
    }

    /**
     * 設置指定包日誌級別             封裝[日誌級別檢測+設置日誌級別+封裝返回值信息]
     * @param packageName           包名
     * @return String               日誌級別信息
     */
    private String setLogger(String packageName,String level){
        boolean isAllowed = isAllowed(level);
        if (isAllowed){
            setLevel(packageName,level);
        }
        return isAllowed
                ? packageName+"日誌等級更改爲:"+level
                : packageName+"日誌等級修改失敗,可用值[ERROR,WARN,INFO,DEBUG,TRACE]";
    }

    /**
     * 獲取制定包的日誌級別
     * @param packageName           包名
     * @return String               日誌級別
     */
    private String getLevel(String packageName){
        Logger logger = loggerContext.getLogger(packageName);
        return hasNull(logger,logger.getLevel())
                ? ""
                : logger.getLevel().toString();
    }

    private boolean hasNull(Object... objects) {
        if (Objects.nonNull(objects)) {
            for (Object element : objects) {
                if (null == element) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 設置制定包的日誌級別
     * @param packageName           包名
     * @param level                 日誌等級
     */
    private void setLevel(String packageName,String level){
        loggerContext.getLogger(packageName).setLevel(Level.toLevel(level));
    }

    //    final String[] levels = {"ERROR","WARN","INFO","DEBUG","TRACE"};
    final String[] levels = {"OFF","FATAL","ERROR","WARN","INFO","DEBUG","TRACE","ALL"};
    /**
     * 判斷是否是合法的日誌級別
     * @param level                 日誌等級
     * @return boolean
     */
    private boolean isAllowed(String level){
        return Arrays.asList(levels).contains(level.toUpperCase());
    }

}

Result.java是web統一返回數據的類,不是必須要的。也可以自己實現。但是這裏也提供一下。

Result.java

/**
 * @ IDE    :IntelliJ IDEA.
 * @ Date   :2019/9/27  16:44
 * @ Desc   :web 統一返回工具類
 */
import java.io.Serializable;
import java.time.LocalDateTime;

public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer code;
    private String msg;
    private  T data;
    private String time;
    public Result(){
        setTime(LocalDateTime.now().toString());
    }
    public Result(Integer code){
        setCode(code).setTime(LocalDateTime.now().toString());
    }
    public Result(Integer code, String msg){
        setCode(code).setMsg(msg).setTime(LocalDateTime.now().toString());
    }
    public Result(Integer code, String msg, T data){
        setCode(code).setMsg(msg).setData(data).setTime(LocalDateTime.now().toString());
    }
    private static final int SUCCESS_CODE = 200;
    private static final int ERROR_CODE = 500;
    private static final String SUCCESS_MSG = "成功";
    private static final String ERROR_MSG = "失敗";
    //成功返回值
    public static Result getSuccessResult() {
        return new Result(SUCCESS_CODE,SUCCESS_MSG);
    }
    public static <T> Result<T> getSuccessResult(T data) {
        return new Result<T>(SUCCESS_CODE,SUCCESS_MSG,data);
    }
    //錯誤返回值
    public static Result getErrorResult() {
        return new Result(ERROR_CODE,ERROR_MSG);
    }
    public static Result getErrorResult(String msg) {
        return new Result(ERROR_CODE,msg);
    }
    //自定義消息
    public static Result getMsgResult(String msg) {
        return new Result(SUCCESS_CODE,msg);
    }
    public static <T> Result<T> getMsgResult(String msg,T data) {
        return getMsgResult(msg).setData(data);
    }
    //自定義返回Code
    public static Result getCodeResult(Integer code,String msg) {
        return new Result(code,msg);
    }
    public static <T> Result<T> getCodeResult(Integer code,String msg,T data) {
        return getCodeResult(code,msg).setData(data);
    }
    public Integer getCode() {
        return code;
    }
    public Result<T> setCode(Integer code) {
        this.code = code;
        return this;
    }
    public String getMsg() {
        return msg;
    }
    public Result<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }
    public T getData() {
        return data;
    }
    public Result<T> setData(T data) {
        this.data = data;
        return this;
    }
    public String getTime() {
        return time;
    }
    public Result<T> setTime(String time) {
        this.time = time;
        return this;
    }
}

推薦閱讀
一個AOP小專題

{
	"author": "大火yzs",
	"title": "SpringBoot不重啓修改日誌級別【Slf4jj動態日誌級別】",
	"tag": "動態日誌,不重啓服務",
	"createTime": "2020-05-19  12:35"
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章