如何动态改变日志级别

article/2025/10/17 5:26:31

前言

关于日志级别,大部分项目可能都设置为info级别,当然也可能有一些追求性能或者说包含很多敏感信息的项目直接将级别设置为warn或者error;这时候如果项目中出现一些未知异常,需要用到很详细的日志信息,此时如果项目中没有动态改变日志级别的机制,排查问题将很棘手。

日志系统

我们常用的一些日志系统包括:Log4j2LogbackJava Util Logging;我们想动态改变日志的级别,前提是这些日志系统都支持我们直接设置日志等级,当然这些系统提供了很简单的接口;

  • Log4j2
LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
LoggerConfig loggerConfig = loggerContext.getConfiguration().getLoggers().get("root");
loggerConfig.setLevel(level);
  • Logback
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger("root");
((ch.qos.logback.classic.Logger) logger).setLevel(level);
  • Java Util Logging
Logger logger = Logger.getLogger("root");
logger.setLevel(level);

当然除了上面直接设置日志级别的方式,也有可以动态加载配置文件的方式,同样也可以在配置文件中动态改变日志级别,以logback为例:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
File externalConfigFile = new File("logback.xml");
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();            
configurator.doConfigure(externalConfigFileLocation);

上面简单介绍了一下每种日志系统都是如何去设置日志级别的,最关键的是设置完之后,可以实时生效,立马可以看到我们想要的日志;有了这些下面其实就是通过何种方式去改变日志级别的问题了;

如何动态改变级别

如何去动态改变级别,最简单的方式就是对外提供一个接口,给定一个日志级别作为参数实时变更;或者通过配置中心的方式;另外其实像SpringBoot这些主流的框架本身也提供了动态修改的功能;下面可以具体看一下是如何实现的,以logback为例;

自定义接口

自定义一个给定日志级别的接口,外部直接通过调用接口来改变级别:

@RequestMapping(value = "logLevel/{logLevel}")
public String changeLogLevel(@PathVariable("logLevel") String logLevel) {try {LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();Logger logger = loggerContext.getLogger("root");((ch.qos.logback.classic.Logger) logger).setLevel(Level.valueOf(logLevel));} catch (Exception e) {logger.error("changeLogLevel error", e);return "fail";}return "success";
}

想要改变日志级别直接请求如下地址即可,设置一个debug的级别:

http://[ip]:[port]/logLevel/debug

这种方式虽然比较简单,但是如果节点很多的话,操作起来就很麻烦,当然也可以汇总所有节点路径,一次操作触发所有节点的请求;其实最好的办法应该是类似发布订阅的方式,发布者会给所有订阅者都发送一个更改日志级别的通知,有新的节点只要成为订阅者即可,这种方式其实就是现在主流的配置中心的方式。

配置中心

配置中心的目的其实就是把一些会经常变动的参数集中保存起来,某个系统启动时去配置中心获取相关的参数,同时会对这些参数进行监听,后面在配置中心里面改变参数的值会实时推送给相关系统;这样系统就可以在不重启的情况下就更新了配置;
利用现有的一些中间件我们就能很快实现一个配置中心,比如Zookeeper提供了对某个Node进行监听的功能,MQ和Redis都有发布订阅的功能,所以用来实时推送变更再好不过了;

  • Zookeeper方式

可以直接使用PathChildrenCache用来监听子节点的CHILD_ADDED,CHILD_UPDATED,CHILD_REMOVED事件;这样如果在Zookeeper服务端对节点的值就行更新,客户端会触发以上三个事件:

private void watcherPath(String path) {PathChildrenCache cache = new PathChildrenCache(client, path, true);cache.start(StartMode.POST_INITIALIZED_EVENT);cache.getListenable().addListener(new PathChildrenCacheListener() {@Overridepublic void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {switch (event.getType()) {case CHILD_ADDED:break;case CHILD_UPDATED:String logLevel = new String(event.getData().getData());//日志级别更新处理break;case CHILD_REMOVED:break;default:break;}}});
}

MQ一般都有Queue和Topic方式,Topic方式其实就是订阅发布模式,所有的集群节点可以订阅某个Topic,这样发布端发送更新日志级别的消息,其他订阅节点都能收到:

//日志等级Topic
private final String TOPIC = "LOGLEVEL";
private void watcherPaths() throws JMSException {Topic topic = session.createTopic(TOPIC);MessageConsumer consumer = session.createConsumer(topic);consumer.setMessageListener(new MessageListener() {@Overridepublic void onMessage(Message message) {TextMessage tm = (TextMessage) message;String logLevel = tm.getText();//日志级别更新处理}});
}

Redis其实除了缓存的功能,也提供了类似MQ的发布订阅的模式;集群节点通过订阅一个channel,发布端通过此channel来发布消息:

private void watcherPaths() throws JMSException {jedis.subscribe(new JedisPubSub() {@Overridepublic void onMessage(String channel, String message) {String logLevel = message;//日志级别更新处理}},"LOGLEVEL");
}

SpringBoot内置

SpringBoot2.0之后可以通过actuator动态调整日志级别,主要是通过暴露loggers这个endpoint来实现,具体步骤如下:

  • 需要引入actuator
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 暴露loggers

在application.properties中添加如下配置:

management.endpoints.web.exposure.include=loggers
  • 查看日志级别

启动服务可以通过:

http://[ip]:[port]/actuator/loggers

查看当前项目每个包的日志级别:

{
levels: ["OFF","ERROR","WARN","INFO","DEBUG","TRACE"
],
loggers: {ROOT: {configuredLevel: "INFO",effectiveLevel: "INFO"},
...
}
  • 动态修改日志级别

发送POST请求到:

http://[ip]:[port]/actuator/loggers/[包路径]

需要在body中指定configuredLevel参数;
比如修改整个项目日志级别为error:

http://[ip]:[port]/actuator/loggers/root

关于SpringBoot内部是如何实现动态改变日志级别的,可以查看其实现核心类LoggersEndpoint:

@Endpoint(id = "loggers")
public class LoggersEndpoint {private final LoggingSystem loggingSystem;@WriteOperationpublic void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) {Assert.notNull(name, "Name must not be empty");this.loggingSystem.setLogLevel(name, configuredLevel);}...
}

具体通过LoggingSystem来对日志系统动态改变级别,上面也介绍了主流使用的日志系统,SpringBoot也都支持这些系统,这是一个抽象类,具体实现类:

  • JavaLoggingSystem
  • Log4J2LoggingSystem
  • LogbackLoggingSystem
  • NoOpLoggingSystem

分别对应了几种日志系统,这几个类内部其实也是调用上面介绍的方法去改变日志级别,当然SpringBoot自动会识别出当前使用的是哪个日志系统,然后使用哪个LoggingSystem;

总结

大部分公司其实更多的还是使用配置中心的方式来动态改变日志级别,这种方式更加灵活,而且配置中心已经成为很多公司的标配组件,不光用来改变日志级别,所有有可能改变的参数都可以使用。

转载:https://blog.csdn.net/kshzhaohui/article/details/111307506


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

相关文章

日志打印的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官网上下载一个…

【解决windows】Windows Linux双系统安装历程,超详细

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

linux和win双系统删除,Windows+Linux 双系统的卸载方法

关于如何在同一台电脑上运行多个操作系统的文章数不胜数,比如有的文章介绍了如何同时安装Windows和Linux,有的文章介绍了如何同时安装Windows和OS X,还有一些其他的文章。但是,当你想卸载其中的某个操作系统,你应该怎么办呢?下面,我们就介绍一下你安装了“Windows+Linux…