平时项目记录日志记录打印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 动态修改日志级别