logback日志动态设置日志级别

153 阅读2分钟

简述

生产环境日志级别一般比较高,用作服务性能优化,但不利于问题排查,通过动态修改日志级别,可以打印出想要的日志,用完再调整回去,简单实用; 以下是单节点的动态调整例子,基于springboot3服务验证过的;
(如果想要在分布式或集群环境进行批量调整,可以通过统一的配置中心或其他方案实现)

maven坐标

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-logging</artifactId>
  <version>3.2.2</version>
  <scope>compile</scope>
</dependency>

实例代码

package com.gjw.demo.controller

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.LoggerContext
import com.example.demo.common.extension.log
import com.example.demo.common.result.BaseResult
import com.example.demo.common.result.R
import com.example.demo.common.result.SingleResult
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.*
import java.util.*


/**
 * 日志级别动态跳转
 */
@RestController
@RequestMapping("/log")
class LoglevelController {

    /**
     * 测试日志输出级别
     */
    @GetMapping("/test")
    fun testLogLeve(): BaseResult {
        /**
         * 日志输出级别的优先级通常按照其重要性和详细程度进行排序。一般而言,
         * 优先级从高到低依次为:FATAL>ERROR>WARN>INFO>DEBUG>TRACE。
         * 这个顺序反映了不同级别日志信息的紧急程度和详细程度。
         * 输出规则是:只有等于或高于该级别的日志信息才会被输出
         */
        log.trace("------我是trace---------");
        log.debug("------我是debug---------");
        log.info("-------我是info----------");
        log.warn("-------我是warn----------");
        log.error("------我是error---------");
        return R.ok("测试成功,请去控制台查看日志输出");
    }

    /**
     * 获取当前日志输出级别
     * @param packageName 包名, 默认为根
     */
    @GetMapping("/now")
    fun getLocalLoggerLevel(@RequestParam(required = false) packageName: String?): SingleResult<String> {
        val pgName = packageName ?: Logger.ROOT_LOGGER_NAME
        // 获取 LoggerContext
        val loggerContext: LoggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
        // 获取 Logger 实例
        val rootLogger: Logger = loggerContext.getLogger(pgName)
        // 获取当前日志级别
        val currentLevel = rootLogger.level
        // 输出当前日志级别
        log.debug("当前日志输出级别为:" + currentLevel.levelStr)
        return R.ok("当前日志输出级别为:" + currentLevel.levelStr) {
            this.data = "$pgName : ${currentLevel.levelStr}"
        }
    }

    /**
     * 更改日志输出级别
     * @param level 日志级别
     * @param packageName 包名, 默认为根
     */
    @GetMapping("/change/{level}")
    fun loggerLevelChange(
        @PathVariable("level") level: String,
        @RequestParam(required = false) packageName: String?
    ): SingleResult<String> {
        val pgName = packageName ?: Logger.ROOT_LOGGER_NAME
        // 获取 LoggerContext
        val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
        // 获取 Logger 实例
        val logger = loggerContext.getLogger(pgName)
        when (level.lowercase(Locale.getDefault())) {
            "debug" -> logger.level = Level.DEBUG
            "info" -> logger.level = Level.INFO
            "warn" -> logger.level = Level.WARN
            "error" -> logger.level = Level.ERROR
            else -> return R.fail("请输入正确的日志级别")
        }
        return R.ok("日志输出级别已切换为:$level") {
            this.data = "$pgName : $level"
        }
    }
}