IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> springboot logback-spring.xml 整合apollo实现动态配置日志级别 -> 正文阅读

[Java知识库]springboot logback-spring.xml 整合apollo实现动态配置日志级别

平时项目记录日志记录打印SQL,打印MQ日志,日志量比较大,一般用INFO,但是项目刚上线,不太稳定一般需要用DEBUG记录详细日志,或者由于项目出现问题,需要调整到DEBUG,查看详情,所以需要支持动态调整日志级别.?

1.配置logback-spring.xml

2.配置application.yml

3.配置apollo参数

4编写apollo变化触发类

5.编写日志测试类

6.测试

1.配置logback-spring.xml

? 配置日志级别log.level ,参数log.level.com.sun.springboot来源于apollo参数

? <springProperty scope="context" name="log.level" source="log.level.com.sun.springboot"/>

?配置logger,日志级别来自上面定义的参数log.level

?<logger name="com.sun.springboot.controller" level="${log.level}"/>

2.配置application.yml
?apollo:
? ?bootstrap:
? ? ?#在应用启动阶段是否向Spring容器注入被托管的properties文件配置信息
? ? ?enabled: true
? ? ?eagerLoad:
? ? ?#将Apollo配置加载提到初始化日志系统之前
? ? ? ? enabled: true

3.配置apollo参数

? ?log.level.com.sun.springboot? info

4编写apollo变化触发类

package com.sun.springboot.controller;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Map;

/**
?* 自动刷新apollo配置
?*/
@Slf4j
@Component
public class LogLevelChanged implements ApplicationContextAware {
? ? private Logger logger = LoggerFactory.getLogger(LogLevelChanged.class);

? ? private ApplicationContext applicationContext;
? ? private String prefix = "log.level.";

? ? @ApolloConfigChangeListener(value = {"application"})
? ? public void onChange(ConfigChangeEvent changeEvent) {
? ? ? ? log.info("================Apollo 自动刷新值 开始 ===========================");

? ? ? ? Map<String, String> logMap = new HashMap<>();
? ? ? ? for (String changeKey : changeEvent.changedKeys()) {
? ? ? ? ? ? changeKey = changeKey.trim();
? ? ? ? ? ? ConfigChange configChange = changeEvent.getChange(changeKey);
? ? ? ? ? ? String oldValue = configChange.getOldValue();
? ? ? ? ? ? String newValue = configChange.getNewValue();

? ? ? ? ? ? if (changeKey.startsWith(prefix)) {
? ? ? ? ? ? ? ? logMap.put(changeKey.substring(prefix.length()), newValue);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? }
? ? ? ? ? ? log.info("changedKey:【{}】,oldValue=【{}】, newValue:【{}】", changeKey,

? ? ? ? ? ? oldValue, newValue);
? ? ? ? }

? ? ? ? changeLogLevel(logMap);
? ? ? ? log.info("================Apollo 自动刷新值 结束 ===========================");
? ? }

? ? private void changeLogLevel(Map<String, String> logMap) {
? ? ? ? LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
? ? ? ? for (String key : logMap.keySet()) {
? ? ? ? ? ? ch.qos.logback.classic.Logger logbackLogger = lc.getLogger(key);
? ? ? ? ? ? logbackLogger.setLevel(Level.toLevel(logMap.get(key)));
? ? ? ? }
? ? }

? ? @Override
? ? public void setApplicationContext(ApplicationContext applicationContext) throws? ? ? ? ? BeansException {
? ? ? ? this.applicationContext = applicationContext;
? ? }
}

5.编写日志测试类

package com.sun.springboot.controller;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Objects;

@RestController
@RequestMapping(value = "log")
public class LogController {
    private static Logger logger = LoggerFactory.getLogger(LogController.class);

    /**
     * 获得日志所在包的日志级别
     *
     * @param pack 所在包的日志级别
     * @return
     */
    @RequestMapping(value = "getLevel")
    public String getLevel(String pack) {
        Logger logger = LoggerFactory.getLogger(LogController.class);
        // 第一步:获取日志上下文
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        // 第二步:获取日志对象 (日志是有继承关系的,关闭上层,下层如果没有特殊说明也会关闭)
        ch.qos.logback.classic.Logger log = lc.getLogger(pack);
        Level level = log.getLevel();
        String result = "";
        if (Objects.isNull(level)) {
            result = String.format("package:%s,level:%s", pack, "null");
        } else {
            result = String.format("package:%s,level:%s", pack, level.toString());
        }

        // 第三步:修改日志级别
        logger.debug("===== 我是 debug  =====");
        logger.info("===== 我是 info  =====");
        logger.error("===== 我是 ERROR  =====");
        return result;
    }
}

6.测试

? 6.1先修改?log.level.com.sun.springboot 为debug

? 6.2? 访问接口:http://localhost:6012/log/getLevel?pack=com.sun.springboot.controller

? 返回:package:com.sun.springboot.controller,level:DEBUG

logback-spring.xml?

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="20 seconds">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <springProperty scope="context" name="log.level" source="log.level.com.sun.springboot"/>

    <property name="LOG_HOME" value="F:/logs-spring"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/debug/debug.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>16</MaxHistory>
            <!--日志文件切割大小-->
            <maxFileSize>20MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/info/info.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>16</MaxHistory>
            <!--日志文件切割大小-->
            <maxFileSize>20MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/warn/warn.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>24</MaxHistory>
            <!--日志文件切割大小-->
            <maxFileSize>20MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
    </appender>
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/error/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>32</MaxHistory>
            <!--日志文件切割大小-->
            <maxFileSize>20MB</maxFileSize>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>
    <logger name="com.sun.springboot.controller" level="${log.level}"/>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <!-- 控制台输出 -->
        <appender-ref ref="STDOUT"/>
        <!--<!– 文件输出 –>-->
        <appender-ref ref="ERROR"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="DEBUG"/>
        <appender-ref ref="WARN"/>
    </root>
</configuration>

参考:springboot apollo 自动刷新_重度孤独症患者的博客-CSDN博客

logback java动态配置【动态修改日志级别,动态修改appender】_keep-go-on的博客-CSDN博客_java 动态修改日志级别

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:56:31  更:2022-09-04 00:58:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:14:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码