工作中,在排查线上问题时,有以下场景在不重新部署或重启服务的情况下,需要动态调整线上日志级别

1、线上有些日志打印过多干扰有用的日志,需要动态修改线上日志记录器的打印日志级别,调高一些日志级别,打印出更少的干扰日志

2、由于线上日志级别打印的相关有用日志太少,需要动态修改线上日志记录器的打印日志级别,调低一些日志级别,打印出更多的有用日志

本文的两个工具类使用的版本如下:

----------------logback---------------------

<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-core</artifactId>
   <version>1.1.8</version>
</dependency>
-----------------log4j2--------------------
<dependency>

   <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-log4j2</artifactId>

   <version>1.5.12.RELEASE</version>

</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>2.7</version>
 </dependency>

-----------------Log4j2Controller-------------------------

@Api(tags = "Log4j2Controller",description = "Log4j2控制类")
@RestController
@RequestMapping("/log/control")
public class Log4j2Controller {
private static final Logger logger = LoggerFactory.getLogger(Log4j2Controller.class); @RequestMapping(value = "/getLoglevel", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public Level getLoglevel(@RequestParam(value="package") String packageName) throws Exception {//package 指定修改日志级别的包路径 ,如 org.mybatis
logger.info("getLoglevel packageName is {}",packageName);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
return ctx.getLogger(packageName).getLevel();
} @RequestMapping(value = "/setLoglevel", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public String setLoglevel(@RequestParam("loglevel") String logLevel, @RequestParam(value="package") String packageName) throws Exception { logger.info("setLoglevel packageName is {},logLevel is {}",packageName,logLevel);
try{
Configurator.setLevel(packageName,Level.valueOf(logLevel));
}catch (Exception e){
logger.error("Exception setLoglevel packageName is {},logLevel is {}",packageName,logLevel,e);
return "fail";
}
return "success";
}
@RequestMapping(value = "/setRootLoglevel", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public String setRootLoglevel(@RequestParam("loglevel") String logLevel) throws Exception {
logger.info("setRootLoglevel ,logLevel is {}",logLevel);
try {
//设置根记录器
Configurator.setRootLevel(Level.valueOf(logLevel));
}catch (Exception e){
logger.error("Exception setRootLoglevel ,logLevel is {}",logLevel,e);
return "fail";
}
return "success";
}
@RequestMapping(value = "/testLoglevel", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public String testLoglevel() throws Exception {
logger.debug("current log level is debug..........debug...");
logger.info("current log level is info.........info......");
logger.warn("current log level is warn.......warn.......");
logger.error("current log level is error.......error......."); return "success";
}
} -----------------LogbackController-------------------------
@Api(tags = "LogbackController",description = "logback控制类")
@RestController
@RequestMapping("/log/control")
public class LogbackController {
private static Logger logger = LoggerFactory.getLogger(LogbackController.class); @RequestMapping(value = "/getLoglevel", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
public Level getLoglevel(@RequestParam(value="package") String packageName) throws Exception {//package 指定修改日志级别的包路径 ,如 org.mybatis
logger.info("getLoglevel packageName is {}",packageName);
LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory();
return loggerContext.getLogger(packageName).getLevel();
} @RequestMapping(value = "/setLoglevel", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String setLoglevel(@RequestParam("loglevel") String logLevel, @RequestParam(value="package") String packageName) throws Exception {
logger.info("setLoglevel packageName is {},logLevel is {}",packageName,logLevel);
try{
LoggerContext loggerContext =(LoggerContext)LoggerFactory.getILoggerFactory();
loggerContext.getLogger(packageName).setLevel(Level.valueOf(logLevel));
}catch (Exception e){
logger.error("Exception packageName is {},logLevel is {}",packageName,logLevel,e);
return "fail";
}
return "success";
} @RequestMapping(value = "/setRootLoglevel", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String setRootLoglevel(@RequestParam("loglevel") String logLevel) throws Exception {
logger.info("setRootLoglevel ,logLevel is {}",logLevel);
try{
LoggerContext loggerContext =(LoggerContext)LoggerFactory.getILoggerFactory();
//设置全局日志级别
ch.qos.logback.classic.Logger logger=loggerContext.getLogger("root");
logger.setLevel(Level.toLevel(logLevel));
}catch (Exception e){
logger.error("Exception setRootLoglevel,logLevel is {}",logLevel,e);
return "fail";
}
return "success";
} @RequestMapping(value = "/testLoglevel", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String testLoglevel() throws Exception {
logger.debug("current log level is debug..........debug...");
logger.info("current log level is info.........info......");
logger.warn("current log level is warn.......warn.......");
logger.error("current log level is error.......error......."); return "success";
}
} 备注:
1、logback和log4j2也有其它方式动态修改日志,但需要有方案或权限修改线上部署服务器的修改权限
比如logback.xml中的configuration标签有<configuration scan="true" scanPeriod="60 seconds" debug="false">这种配置,
其中的scan如果设置为true的话,项目在启动后就会默认每一分钟自动扫描配置文件,如果有改变则重新加载,而我们还可以设置自动扫描的时间间隔属性scanPeriod,可以设置成30秒或者5分钟。
现在只要在logback.xml中添加一个属性,以后可以直接在服务器上修改logback.xml中root的level属性或者直接替换整个logback.xml文件,然后过会项目的日志输出级别就会改变了,不需要再重启项目。
2、本文主要介绍代码动态修改线上日志级别
3、log4j2遇到的坑,如果把某个logger的日志级别修改成debug,日志文件一直不会打印,但控制台会正常打印。
经排查是log4j2.xml中appender的过滤级别配置导致的,如下:
修改前:
<Filters>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
   修改后:
<Filters>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
</Filters> 简单对比说明:
onMatch和onMismatch都有三个属性值:Accept、DENY和NEUTRAL
onMatch="ACCEPT" 表示匹配该级别及以上
onMatch="DENY" 表示不匹配该级别及以上
onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上
onMismatch="ACCEPT" 表示匹配该级别以下
onMismatch="NEUTRAL" 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
onMismatch="DENY" 表示不匹配该级别以下的



log4j2和logback动态修改日志级别工具类的更多相关文章

  1. Logback动态修改日志级别

    https://blog.csdn.net/totally123/article/details/78931287

  2. log4j2动态修改日志级别及拓展性使用

    一.供参考的完整日志配置 <?xml version="1.0" encoding="UTF-8"?> <!-- 配置LoggerConfig ...

  3. SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别)

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot整合Restful架构 2.背景 Spring 与 Restful 整合才是微架构的核心,虽然在整 ...

  4. springboot动态修改日志级别+权限认证

    1. springboot动态修改日志级别+权限认证 1.1. 需求 网上找到的动态修改日志级别的方式,基本都是没有权限验证的,或者特地关闭权限验证,但也没给出加上验证的解决方式 修改日志等级也是一个 ...

  5. [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤

    作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...

  6. Spring Boot动态修改日志级别

    1. pom中引入 org.springframework.boot       spring-boot-starter-actuator 2. 发送POST请求: 地址: http://[服务地址] ...

  7. 动态调整日志级别思路&实现

    引言 上篇文章 性能调优--小小的 log 大大的坑 已将详细的介绍了高并发下,不正确的使用日志姿势,可能会导致服务性能急剧下降问题.文末也给各位留下了解决方案--日志级别动态调整. 本文将详细介绍& ...

  8. springboot2整合logback.xml动态修改日志打印级别

    今天找bug烦到了,生产上的日志级别不能修改,非常不利于排查问题,于是想到了动态修改日志打印级别, 因为上一周把项目升级成springboot2,并且使用logback.xml管理日志打印,所以修改也 ...

  9. Log4cpp配置文件及动态调整日志级别的方法

    一.log4cpp概述 Log4cpp是一个开源的C++类库,它提供了C++程序中使用日志和跟踪调试的功能,它的优点如下: 提供应用程序运行上下文,方便跟踪调试: 可扩展的.多种方式记录日志,包括命令 ...

随机推荐

  1. Java Integer Addition Subtration Overflow 整数加减溢出

    leetCode有道题Reverse Integer,因为int的最大值为2的31次方减一,最小值为-2的31次方. 我一开始的代码将res递归加放在try中,以为溢出会有异常,然而并没有. 因为出传 ...

  2. PHP笔记01

    php 环境 xamp wamp phpstudy等集成软件网上很多 PHP基础语法 PHP语法是以<?php开始 ?>结束的//php 文件的默认扩展名是.php 例如(用PHP输出he ...

  3. RobotFramwork中实现oracle数据库的连接(终于解决cx_oracle问题)

    RobotFramework连接数据库有java实现,也有python实现的,现在研究的python实现的,java还没尝试.有兴趣的参考后面的转载文章.     步骤(也转载了别人的文章,因为写的比 ...

  4. npm - 换淘宝源

    npm - 换淘宝源Node 的模块管理器 npm 会一起安装好.由于 Node 的官方模块仓库网速太慢,模块仓库需要切换到阿里的源. $ npm config set registry https: ...

  5. 《百面机器学习算法工程师带你去面试》高清PDF及epub+《美团机器学习实践》PDF及思维导图

    http://blog.sina.com.cn/s/blog_ecd882db0102yuek.html <百面机器学习算法工程师带你去面试>高清PDF及epub+<美团机器学习实践 ...

  6. QT设计

    MFC是跨平台的一个界面开发的类库 框架是什么呢? 1.基础模块 2.机制交互(数据传输) 3.多种语言 QT core QT gui QT widget QT 1.基础模块 2.拓展模块 3.too ...

  7. LIS是什么?【标本分拣】

    接之前[LIS是什么?]中,提到几点需要补充描述的部分. Ⅰ.标本分管处理 标本的分管处理,在医院和第三方实验室有多种叫法,例如:分拣.合管等等.这里我称之为分拣,分拣实际上分为两个部分:系统中标本分 ...

  8. linux中redis伪主从搭建

    1.解压redis.tgz到usr/local/redis下 2.在redis/下执行 make 3.在redis/src/下执行 make install PREFIX=/usr/local/red ...

  9. Day 9:双列集合Map及实现该接口的类的常用方法

    为什么要学双列集合? 因为单列集合无法处理映射关系,会有成对出现的数据 Map接口  如果是实现了Map接口的集合类,具备的特点: 存储的数据都是以键值对的形式存在的,键不可重复,值可以重复 Map接 ...

  10. webUploader多个实例

    webUploader上传图片插件一个页面多个实例多处使用