<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
動態調整線上紀錄檔級別是一個非常常見的場景,藉助apollo這種設定中心元件非常容易實現。作為apollo的官方技術支援,博主經常在技術群看到有使用者詢問apollo是否可以託管logback的組態檔,畢竟有了設定中心後,消滅所有的本地設定全部交給apollo管理是我們的最終目標。可是,apollo不具備直接託管logback-spring.xml組態檔能力,但是,我們可以基於spring和logback的裝載機制,完全取締logback-spring.xml設定,以apollo中的設定驅動。而且,改造後,大大提高了紀錄檔系統的靈活性和可延伸性。
何為apollo動態紀錄檔?直接這樣說可能會有歧義,以為是apollo裡的紀錄檔,其實不然。舉個簡單的例子,比如,我們專案很多地方使用了log.debug()列印紀錄檔,為了方便通過紀錄檔資訊排查問題,但是一般情況下,生產環境的紀錄檔級別會設定成info。只有遇到需要排查線上問題的時候才會臨時開啟debug級別紀錄檔。這個時候只能需改組態檔,將紀錄檔級別調整成debug,然後重新打包部署驗證。不僅流程繁瑣耗時,還會破壞當時的"案發現場的環境",導致判斷不準確。如果應用具備了apollo動態紀錄檔這種能力,就只需在apollo修改下設定然後提交,就可以熱更新紀錄檔級別,馬上列印debug級別紀錄檔。這就是所謂的apollo動態紀錄檔。實現這個效果,需要具備兩個能力,分別由spring和apollo提供
spring應用中,spring適配了主流的紀錄檔框架,如logback、log4j2等,在這些紀錄檔框架之上,又抽象了自己的紀錄檔系統服務,這裡我們用到了spring的LoggingSystem,用它來熱更新紀錄檔級別,這個類在紀錄檔系統初始化時就新增到了spring的容器中,所以只要在spring的上下文管理範圍內,就可以直接注入,以下為主要使用到的api描述:
/** * 設定給定紀錄檔記錄器的紀錄檔級別. * @param loggerName 要設定的紀錄檔記錄器的名稱({@code null}可用於根紀錄檔記錄器)。 * @param level 紀錄檔級別 */ public void setLogLevel(String loggerName, LogLevel level) { throw new UnsupportedOperationException("Unable to set log level"); }
apollo作為分散式設定中心,設定集中管理和設定熱更新是其最核心的功能,此外,apollo還提供了設定變更下發監聽的功能。基於這個設定監聽的設計,實現動態紀錄檔就變得非常簡單了。而且不僅可以實現紀錄檔動態熱更,基於這個思路,連線池、資料來源等都可以輕鬆實現。apollo實現監聽設定變更有多種方式,可以通過Config範例手動新增,如:
@ApolloConfig public Config config; public void addConfigChangeListener(){ config.addChangeListener(changeEvent->{ System.out.println("config change keys" + changeEvent.changedKeys()); }); }
也可以通過註解直接驅動
@ApolloConfigChangeListener public void addConfigChangeListener(ConfigChangeEvent changeEvent){ System.out.println("config change keys" + changeEvent.changedKeys()); }
有了上述能力,在結合spring支援的紀錄檔載入設定方式,如:
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
可以實現如下程式碼完成功能,遇到需要調整紀錄檔級別時,修改apollo裡的設定,即可實時生效
@Configuration public class LogbackConfiguration { private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class); private static final String LOGGER_TAG = "logging.level."; private final LoggingSystem loggingSystem; public LogbackConfiguration(LoggingSystem loggingSystem) { this.loggingSystem = loggingSystem; } @ApolloConfigChangeListener private void onChange(ConfigChangeEvent changeEvent) { for (String key : changeEvent.changedKeys()) { if (this.containsIgnoreCase(key, LOGGER_TAG)) { String strLevel = changeEvent.getChange(key).getNewValue(); LogLevel level = LogLevel.valueOf(strLevel.toUpperCase()); loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level); logger.info("logging changed: {},oldValue:{},newValue:{}", key, changeEvent.getChange(key).getOldValue(), strLevel); } } } private boolean containsIgnoreCase(String str, String searchStr) { if (str == null || searchStr == null) { return false; } int len = searchStr.length(); int max = str.length() - len; for (int i = 0; i <= max; i++) { if (str.regionMatches(true, i, searchStr, 0, len)) { return true; } } return false; } }
在"消滅"logback-xml設定之前,先看下這個組態檔有哪些設定資訊,起到了哪些作用,下面貼出一個典型的組態檔內容:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> <appender name="Sentry" class="io.sentry.logback.SentryAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> </appender> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="Sentry"/> </root> <logger name="org.apache.ibatis.session" level="WARN"/> <springProfile name="dev"> <logger name="com.taptap.server" level="DEBUG"/> <logger name="com.taptap.commons" level="DEBUG"/> </springProfile> <springProfile name="prod"> <logger name="com.taptap.server" level="WARN"/> <logger name="com.taptap.commons" level="WARN"/> </springProfile> </configuration>
一個典型的logback組態檔裡包含了Appender和紀錄檔級別設定的資訊,Appender可以理解為紀錄檔的輸出源。如上貼出的這個設定,新增了兩個Appender資訊,一個是spring中內建的,將紀錄檔輸出到控制檯的Appender。一個是將error紀錄檔資訊傳送到Sentry應用監控平臺的Appender。其他的設定描述了每個包路徑不同的紀錄檔級別資訊。到這裡,我們很容易想到,上文已經說過,spring已經支援以logging.level.包名=info這種設定來設定紀錄檔系統的紀錄檔級別。那麼剩下的只要解決Appender的設定就ok了。在這裡,其實只需要解決SentryAppender的載入就行,因為consoleAppender spring自己會處理。有了目標和方向,就好辦了。以logback-spring.xml設定的資訊,最終都會載入成class物件。就和spring.xml設定一樣。所以研究的方向就變成了Logback的載入原理的問題。
在java的紀錄檔生態裡,除了響噹噹的logback、log4j2、apache common log外,還有一個紀錄檔框架不得不提,就是sl4j。正因為java生態強大,紀錄檔框架層出不窮,所以sl4j出來了,不幹實事,專門定義紀錄檔標準、規範定義介面。而且,在我們平時的編碼過程中,也建議使用sl4j的api,這樣,無論底層紀錄檔框架實現怎麼切換,都不會影響。主流的紀錄檔框架都有實現sl4j的介面,spring中紀錄檔系統的載入也是面向的sl4j,而不是直接面向紀錄檔實現,載入過程是一個自動化的過程,系統會自動掃描實現了sl4j的介面實現,如:
public interface ILoggerFactory { public Logger getLogger(String name); }
每個紀錄檔框架都會實現這個介面,如Logback中的LoggerContext。Logback所有的功能都整合在了這個Context中,logback-spring.xml的設定也是為了設定LoggerContext中的屬性資訊,所有我們只要拿到了LoggerContext範例,問題就解決了一大半。這涉及到sl4j的另一個介面,獲取ILoggerFactory範例的介面:
public interface LoggerFactoryBinder { public ILoggerFactory getLoggerFactory(); public String getLoggerFactoryClassStr(); }
Logback的實現類為StaticLoggerBinder,也就是說,我們可以通過StaticLoggerBinder的getLoggerFactory方法拿到LoggerContext範例了。
拿到Logback的LoggerContext後,就好辦了,見程式碼:
@Configuration public class LogbackConfiguration { private final LoggerContext ctx = (LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory(); @Bean @Profile(PROD_ENV) public void initSenTry() { SentryAppender sentryAppender = new SentryAppender(); sentryAppender.setContext(ctx); ThresholdFilter filter = new ThresholdFilter(); filter.setLevel(Level.ERROR.levelStr); filter.start(); sentryAppender.addFilter(filter); sentryAppender.start(); ctx.addTurboFilter(new TurboFilter() { @Override public FilterReply decide(Marker marker, ch.qos.logback.classic.Logger logger, Level level, String format, Object[] params, Throwable t) { logger.addAppender(sentryAppender); return FilterReply.NEUTRAL; } }); } }
看到這種程式碼就非常有感覺了,組態檔中的xml其實就是描述了紀錄檔組成物件以及物件的屬性。在使用java bean的方式設定時需要注意,Logback的設計裡,每個紀錄檔系統組成範例都有一個start狀態屬性,上面的start()方法其實不是動作,只是標記了這個屬性為true。而在xml裡這個屬性只要設定了就自動啟用為true了,這裡必須顯示的start()一下。解決了紀錄檔級別設定和Appender設定後,Logback-spring.xml檔案就可以徹底的刪除了
以上就是整合apollo動態紀錄檔取締logback-spring.xml設定的詳細內容,更多關於apollo動取締logback-spring.xml設定的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45