日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态刷新日志级别

發布時間:2024/3/24 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态刷新日志级别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

日志模塊是每個項目中必須的,用來記錄程序運行中的相關信息。一般在開發環境下使用DEBUG級別的日志輸出,為了方便查看問題,而在線上一般都使用INFO級別的日志,主要記錄業務操作的日志。那么問題來了,當線上環境出現問題希望輸出DEBUG日志信息輔助排查的時候怎么辦呢?修改配置文件,重新打包然后上傳重啟線上環境,但是這么做不優雅 而且可能會破壞現場。

本文介紹一種實現方案:通過Apollo配置中心來實現 動態調整線上日志級別。

日志級別

不同的日志框架支持不同的日志級別,其中比較常見的就是Log4j和Logback。

在Log4j中支持8種日志級別,優先級從高到低依次為:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。

Logback中支持7種日志級別,優先級從高到低分別是:OFF、ERROR、WARN、INFO、DEBUG、TRACE、ALL。

可以看到常見的ERROR、WARN、INFO、DEBUG,這兩者都是支持的。

所謂設置日志的輸出級別表示的是輸出的日志的最低級別,也就是說,如果我們把級別設置成INFO,那么包括INFO在內以及比INFO優先級高的級別的日志都可以輸出。

Spring Boot對日志的支持

Spring Boot 對log做了統一封裝,代碼在 org.springframework.boot.logging 包中,結構如下:

其中 org.springframework.boot.logging.LoggingSystem 是SpringBoot對日志系統的抽象,是一個頂層的抽象類,有很多具體的實現:

通過上圖,我們可以發現目前SpringBoot目前支持3種類型的日志,分別是

  • JDK內置的Log(JavaLoggingSystem)
  • Log4j2(Log4J2LoggingSystem)
  • Logback(LogbackLoggingSystem)。
  • static {Map<String, String> systems = new LinkedHashMap<>();systems.put("ch.qos.logback.core.Appender", "org.springframework.boot.logging.logback.LogbackLoggingSystem");systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory","org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");systems.put("java.util.logging.LogManager", "org.springframework.boot.logging.java.JavaLoggingSystem");SYSTEMS = Collections.unmodifiableMap(systems);}

    LoggingSystem是個抽象類,內部有這幾個方法:

  • beforeInitialize方法:日志系統初始化之前需要處理的事情。抽象方法,不同的日志架構進行不同的處理
  • initialize方法:初始化日志系統。默認不進行任何處理,需子類進行初始化工作
  • cleanUp方法:日志系統的清除工作。默認不進行任何處理,需子類進行清除工作
  • getShutdownHandler方法:返回一個Runnable用于當jvm退出的時候處理日志系統關閉后需要進行的操作,默認返回null,也就是什么都不做
  • getSupportedLogLevels: 返回日志系統實際支持的一組 LogLevel。
  • setLogLevel方法:抽象方法,用于設置對應logger的級別
  • get方法:檢測并返回正在使用的日志系統。支持 Logback 和 Java 日志記錄。
  • 代碼

    我們可以將日志級別配置保存在Apollo配置中心中, 當日志級別發生變更時,我們需要通過監聽該配置的變更,設置應用中的 Logger 的日志級別,從而后續的日志打印可以根據新的日志級別

    @Slf4j @Component public class LoggingSystemAdjustListener {/*** 日志配置項的前綴*/private static final String LOGGER_PREFIX = "logging.level.";@Resourceprivate LoggingSystem loggingSystem;// By default only read config in "application"@ApolloConfigChangeListenerpublic void onChange(ConfigChangeEvent changeEvent) throws Exception {// <Y> 遍歷配置集的每個配置項,判斷是否是 logging.level 配置項for (String key : changeEvent.changedKeys()) {// 如果是 logging.level 配置項,則設置其對應的日志級別if (key.startsWith(LOGGER_PREFIX)) {String loggerName = key.replace(LOGGER_PREFIX, "");//LoggerConfiguration cfg = loggingSystem.getLoggerConfiguration(loggerName);if (cfg == null) {if (log.isErrorEnabled()) {log.error("no loggerConfiguration with loggerName:{}", loggerName);}continue;}// 獲得日志級別ConfigChange change = changeEvent.getChange(key);// the newLevel could be null if the config is deleted from apollo// in this case we update it same as "root" levelString newLevel = change.getNewValue();LogLevel level = null;// config is deleted or kept as empty stringif (newLevel == null || newLevel.isEmpty()) {level = getFallbackLogLevel(ROOT_LOGGER_NAME);} else {try {level = LogLevel.valueOf(newLevel.toUpperCase());} catch (IllegalArgumentException e) {// do nothing}}if (level == null) {if (log.isErrorEnabled()) {log.error("logger:[{}]current LogLevel is invalid:{}", loggerName, newLevel);}continue;}if (!isSupportLevel(level)) {if (log.isErrorEnabled()) {log.error("LoggingSystem:[] not support current LogLevel:{}",loggingSystem.getClass().getName(), newLevel);}continue;}if (log.isInfoEnabled()) {log.info("logger:[{}] current effective level:{}, to be changed to level:{}", loggerName,cfg.getEffectiveLevel(), newLevel);}// 基于springboot的日志抽象類,設置日志級別到 LoggingSystem 中loggingSystem.setLogLevel(loggerName, level);}}}private boolean isSupportLevel(LogLevel level) {for (LogLevel ll : loggingSystem.getSupportedLogLevels()) {if (ll == level) {return true;}}return false;}public LogLevel getFallbackLogLevel(String loggerName) {LoggerConfiguration cfg = loggingSystem.getLoggerConfiguration(loggerName);if (cfg == null) {if (log.isErrorEnabled()) {log.error("no loggerConfiguration with loggerName:{}", loggerName);}// use WARN as unexpected casereturn LogLevel.WARN;}return cfg.getEffectiveLevel();}}

    基于spring的日志支持,我們還可以在logback中通過logger標簽對某一個包甚至類單獨配置日志級別

    <logger name="com.ethan.demo.log.controller" level="INFO" additivity="true"><appender-ref ref="${CONSOLE_APPENDER}"/></logger>

    總結

    以上是生活随笔為你收集整理的动态刷新日志级别的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。