动态刷新logback日志级别

article/2025/10/17 5:37:09

目录

基础环境准备

pom依赖

Redis工具类

测试类

实现思路及过程

思路

redis中的系统参数

缓存工具类

动态更改日志级别

定时任务定时刷新日志级别

测试效果


最近我们开发了一个Java程序,并没有用到Springboot,对于Springboot程序想要实现动态刷新日志级别是很容易的,只要借助于LoggingSystem 类和 Nacos 就可以轻松实现,这里记录一下在借助于logback的日志的上下文对象LoggerContext来实现动态刷新日志级别,大致思路:通过LoggerFactory获取日志的上下文对象LoggerContext,然后再获取所有的日志类,最后遍历设置对应的日志级别即可。

希望对大家有帮助,如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️,满足一下我的虚荣心💖🙏🙏🙏 。

基础环境准备

pom依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.3.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.3.3.RELEASE</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version><scope>compile</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.2</version></dependency>

Redis工具类

package com.yjh.learn.logbacklearn.utils;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** @author yjh*/
public class JedisUtil {private static JedisPool jedisPool;static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(30);config.setMaxIdle(10);config.setMaxWaitMillis(5000L);config.setTestOnBorrow(true);config.setTestOnReturn(true);config.setTestWhileIdle(true);config.setMinEvictableIdleTimeMillis(60000L);config.setTimeBetweenEvictionRunsMillis(3000L);config.setNumTestsPerEvictionRun(-1);jedisPool = new JedisPool(config, "127.0.0.1", 6379, 60000, null, 0);}public static String get(String key) {String value = null;Jedis jedis = null;try {jedis = jedisPool.getResource();value = jedis.get(key);} catch (Exception e) {e.printStackTrace();} finally {close(jedis);}return value;}public static void close(Jedis jedis) {try {if (jedis != null) {jedis.close();}} catch (Exception e) {if (jedis.isConnected()) {jedis.quit();jedis.disconnect();}}}}

测试类

@RestController
public class TestController {private static final Logger logger = LoggerFactory.getLogger(TestController.class);@GetMapping("/test")public void test() throws Exception{while (true){Thread.sleep(2000);logger.debug("--- debug ---");logger.info("--- info ---");logger.warn("--- warn ---");}}
}

实现思路及过程

思路

将日志级别、对哪个目录生效等作为系统参数放到redis中,当需要更改项目的日志级别的时候,修改下redis中的日志级别参数,程序中会有一个读取缓存的工具类来获取日志级别,然后还需要一个定时器定时的将最新的日志级别更新到Logger类中,这样就完成了日志级别的动态修改。

redis中的系统参数

日志级别、生效包路径作为系统参数缓存到redis中,现在redis中有如下参数:

其中loggerLevel为默认日志级别值为info,loggerPackage为生效的包路径,值为我项目的包路径,另外我还加了一个loggerEnable参数,下面用到了再说。

缓存工具类

redis中已经有了我们想要的数据,现在需要一个读取redis数据的工具类,如下:

import org.apache.commons.lang3.StringUtils;/*** @author yjh*/
public class CacheUtil {private static final String SYS_PARAM_PREFIX = "sys:param:";private static final String LOGGERPACKAGE = "loggerPackage";private static final String LOGGERLEVEL = "loggerLevel";private static final String LOGGERENABLE = "loggerEnable";public static String loggerPackage = "com.yjh.learn.logbacklearn";public static String loggerLevel = "info";public static boolean loggerEnable = false;public static String getLoggerpackage() {String loggerPackageVal = JedisUtil.get(SYS_PARAM_PREFIX + LOGGERPACKAGE);if (StringUtils.isNotBlank(loggerPackageVal)) {loggerPackage = loggerPackageVal;}return loggerPackage;}public static boolean getLoggerenable() {String loggerEnableVal = JedisUtil.get(SYS_PARAM_PREFIX + LOGGERENABLE);if (StringUtils.isNotBlank(loggerEnableVal)) {loggerEnable = Boolean.parseBoolean(loggerEnableVal);}return loggerEnable;}public static String getLoggerlevel() {String loggerLevelVal = JedisUtil.get(SYS_PARAM_PREFIX + LOGGERLEVEL);if (StringUtils.isNotBlank(loggerLevelVal)) {loggerLevel = loggerLevelVal;}return loggerLevel;}
}

为了避免空指针,这里我将loggerPackage、loggerLevel、loggerEnable都设置了默认值。

动态更改日志级别

refreshLoggerLevel方法中有两个参数,loggerPackage为日志级别生效的包路径,, Level loggerLevel为要设置的日志级别,最终通过Logger类的setLevel方法更改日志级别。

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;import java.util.List;
import java.util.stream.Collectors;/*** @author yjh*/
public class RefreshLoggerLevel {private static final String LEVELDEBUG = "debug";private static final String LEVELINFO = "info";private static final String LEVELWARN = "warn";private static final String LEVELERROR = "error";public static void refreshLoggerLevel(String loggerPackage, Level loggerLevel) {LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();List<ch.qos.logback.classic.Logger> loggerList = loggerContext.getLoggerList();List<ch.qos.logback.classic.Logger> packageLoggerList = loggerList.stream().filter(a -> a.getName().startsWith(loggerPackage)).collect(Collectors.toList());for (ch.qos.logback.classic.Logger logger : packageLoggerList) {logger.setLevel(loggerLevel);}}public static Level getLevel(String level) {if (LEVELDEBUG.equals(level)) {return Level.DEBUG;} else if (LEVELINFO.equals(level)) {return Level.INFO;} else if (LEVELWARN.equals(level)) {return Level.WARN;} else if (LEVELERROR.equals(level)) {return Level.ERROR;} else {return Level.INFO;}}}

定时任务定时刷新日志级别

import ch.qos.logback.classic.Level;
import com.yjh.learn.logbacklearn.extend.RefreshLoggerLevel;
import com.yjh.learn.logbacklearn.utils.CacheUtil;import javax.annotation.Resource;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** @author yjh*/
@SuppressWarnings("all")
public class RefreshLevel {private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();public static void refreshLevel() {EXECUTOR.scheduleAtFixedRate(() -> {boolean enable = CacheUtil.getLoggerenable();if (enable) {String level = CacheUtil.getLoggerlevel();System.out.println("refreshLevel level=" + level);Level lv = RefreshLoggerLevel.getLevel(level);RefreshLoggerLevel.refreshLoggerLevel(CacheUtil.getLoggerpackage(), lv);}}, 0, 30, TimeUnit.SECONDS);}
}

如上,我添加了一个定时任务,每30秒执行一次,并且只有当loggerEnable为true时才刷新日志级别,这个loggerEnable参数是可以去掉的,我这里加这个参数,是防止不小心对loggerLevel参数进行了改动,所以才用两个参数进行日志级别刷新的控制。

最后,别忘了触发一下这个定时任务的执行,如果你是在纯java项目中,需要在main方法中调用一下refreshLevel方法,我这里是在Springboot中,所以我使用如下方法触发定时任务的执行:

    @PostConstructpublic void refreshLevel() {RefreshLevel.refreshLevel();}

测试效果

启动项目,调用一下 http://localhost:8080/test  ,控制台打印如下:

此时我们修改redis缓存中的loggerLevel为debug,loggerEnable为true,等30秒后,就会发现debug日志也在控制台进行了打印,如下:


http://chatgpt.dhexx.cn/article/Oi88XjYj.shtml

相关文章

docker 日志级别

- CORE_LOGGING_LEVELINFO #日志级别,critical,error,warning,notice,info,debug从高到低 docker 日志查看命令&#xff1a; docker logs -f -t --tail100 c337e9df72a7 指的是实时查看容器id为c337e9df72a7的最后100行日志 $ docker logs [OPTIONS] CONTAINER Options: …

如何动态改变日志级别

前言 关于日志级别&#xff0c;大部分项目可能都设置为info级别&#xff0c;当然也可能有一些追求性能或者说包含很多敏感信息的项目直接将级别设置为warn或者error&#xff1b;这时候如果项目中出现一些未知异常&#xff0c;需要用到很详细的日志信息&#xff0c;此时如果项目…

日志打印的8种级别(很详细)

日志的输出都是分级别的&#xff0c;不同的设置不同的场合打印不同的日志。下面拿最普遍用的Log4j日志框架来做个日志级别的说明&#xff0c;其他大同小异。 Log4j的级别类org.apache.log4j.Level里面定义了日志级别&#xff0c;日志输出优先级由高到底分别为以下8种。 日志级…

log4j日志级别

log4j日志级别 Log4j的级别类org.apache.log4j.Level里面定义了日志级别&#xff0c;日志输出优先级由高到底分别为以下8种。 日志级别: OFF | 关闭&#xff1a;最高级别&#xff0c;不打印日志。FATAL | 致命&#xff1a;指明非常严重的可能会导致应用终止执行错误事件。ERR…

日志级别----

日志级别 从小到大 ALL、DEBUG 、INFO、WARA、ERROR 、FATAL 、OFF ALL&#xff08;输出所有类型日志&#xff09; DEBUG &#xff08;输出DEBUG 以上级别日志&#xff09; INFO&#xff08;输出INFO以上级别日志&#xff09; WARA&#xff08;输出WARA以上级别日志&#xff09…

win10+kali linux双系统安装教程

win10安装kali linux双系统 准备工作制作启动U盘安装win10Kali双系统我遇到的问题我参考的链接 kali linux是基于Debian的Linux发行版&#xff0c;与任何一个其它的 Linux 发行版一样&#xff0c;可以将它永久安装到一个硬盘上。那样它会工作的更好。但是不能将它作为一个日常使…

Windows和Linux双系统安装教程

1 系统启动盘准备 因为不想装第二个系统的时候重做系统盘&#xff0c;所以这里做的系统启动盘本身就是Windows和Linux双系统引导的。这里用的工具前面在docker安装笔记的时候已经介绍过&#xff1a;YUMI。可以翻翻前面的博客进行了解。 花式安装蓝鲸鱼札记 百度搜索的时候&a…

双系统之删除Linux

本文环境&#xff0c;win10Ubuntu。 先删除引导再操作卷 因为之前想学习Linux&#xff0c;所以就在win10上又安装了Ubuntu&#xff0c;现在不想搞了&#xff0c;再加上win10空间不太够用了&#xff0c;就想删除linux系统。话不多说&#xff0c;直接开始。 删除Linux主要分为两部…

双操作系统安装(五)Windows及Manjaro Linux双系统安装教程

1 前提&#xff1a;请先安装Windows系统&#xff0c;再进行Manjaro系统安装&#xff0c;不要将两者顺序颠倒&#xff0c;否则安装完成后无法引导Manjaro系统&#xff1b; 2 此文以Windows10为例&#xff0c;安装Windows过程略&#xff1b; 3 在Windows系统中为Manjaro单独划分…

Windows与Linux双系统设置默认引导项与删除引导项

当电脑中安装了Windows和Linux双系统&#xff0c;但是每次开机默认自动进入Linux系统时&#xff0c;有时根本来不及选择&#xff0c;平时常用的系统却是Windows&#xff0c;于是我们需要让电脑默认选择Windows系统启动。 安装了Windows和Linux双系统后&#xff0c;系统启动交给…

linux双系统uefi启动顺序,UEFI下Windows启动引导的顺序(附带linux双系统)

这里均以64位系统(windows和linux均是),gpt分区,UEFI引导作为例子,现在基本上不会不支持吧。 windows下UEFI引导文件的载入顺序 主板启动windows的一般有两种方法: windows boot manager启动 硬盘直接引导启动 主板bios中分别是途中前两项(第二项是你自己的硬盘名称,我这里…

双操作系统安装(三)Windows及Deepin深度linux双系统安装教程

1 前提&#xff1a;请先安装Windows系统&#xff0c;再进行Deepin系统安装&#xff0c;不要将两者顺序颠倒&#xff0c;否则安装完成后无法引导Deepin系统&#xff1b; 2 此文以Windows10为例&#xff0c;安装Windows过程略&#xff1b; 3 在Windows系统中为Deepin单独划分一…

MacBook Pro macOS 安装 Linux 双系统教程(一)

前言 macOS已经很不错了&#xff0c;为什么还要安装Linux了&#xff1f; 网上看到的解释很多&#xff0c;虽然我已经安装了window的双系统 Linux 各个发行版与 macOS 相比哪个写代码更舒服&#xff1f;为什么&#xff1f;[^1] 其实最主要的需求还是资源有限吧&#xff0c;从…

Windows + Linux 双系统的安装

Windows Linux 双系统的安装 参考自 https://blog.csdn.net/flyyufenfei/article/details/79187656 参考自 https://blog.csdn.net/u012052268/article/details/77145427 文章目录 Windows Linux 双系统的安装1. 准备工作1.1 U盘启动盘的制作1.2 分配磁盘空间 2. 安装 ubunt…

​Window Linux 双系统安装历程,超详细

Window Linux 双系统安装历程 今天下午搞了几个小时&#xff0c;可谓是困难重重&#xff0c;但是实际上只是被一个很小的问题困住了&#xff0c;其它地方都很简单。 接下来简单讲一下安装的步骤以及遇到的问题。 先讲一下设备状况&#xff1a; 一台 12 年买的 i3 window7 待…

win7和kali linux双系统安装

1&#xff0c;首先下载kali linux https://www.kali.org/downloads/&#xff0c;根据自己的电脑选择32位或64位 2.然后开始刻录U盘&#xff0c;使用win32diskimager进行刻盘&#xff0c;否则在安装时会出现无法加载光盘文件等错误&#xff0c;https://sourceforge.net/projects…

Rockchip RK3588 Android+Linux双系统方案的实现

Rockchip RK3588 AndroidLinux双系统方案的实现 文章目录 Rockchip RK3588 AndroidLinux双系统方案的实现概述硬件环境软件环境要求代码修改uboot引导不同的系统修改parameter分区表修改Android系统的fstabLinux系统固件 固件烧写验证 概述 RK3588双系统启动流程如下图 uboo…

windows加linux双系统安装方法

windows中标麒麟或中科方德的双系统安装方法 如果需要安装windows和linux系统双系统&#xff0c;需要先安装windows&#xff0c;windows的安装方法就不在这里说明了&#xff0c;安装了windows系统后再安装linux系统。 一、windows和中科方德双系统安装方法 1、安装windows后重启…

linux双系统安装教程

最近刚刚完成了Windows和Linux双系统(这里以Ubuntu安装为例)的安装,应某奔同学要求,这里简单记录下安装过程。 1 系统启动盘准备 因为不想装第二个系统的时候重做系统盘,所以这里做的系统启动盘本身就是Windows和Linux双系统引导的。这里用的工具前面在docker安装笔记的…

在windows系统下安装linux双系统

其实是不难的&#xff0c;只是要注意一些小细节&#xff1b;&#xff08;主要问题有两个&#xff1a;1.怎么进入自己电脑的bios 2.安装linux过程中的分区大小问题&#xff0c;后面会详细描述我遇到的这方面的问题&#xff09; 步骤如下&#xff1a; 1.去ubuntu官网上下载一个…