在一些场景中,需要在不重启应用的情况下改变日志级别。本文介绍一种基于freemarker 模板和zookeeper配置调整日志级别的方法。
logback本身提供了运行时更新日志配置的接口。
logback提供了JoranConfigurator类给开发者配置logback,默认情况下,JoranConfigurator会寻找默认的配置文件,配置logback,比如classpath下的logback.xml文件。
JoranConfigurator也允许开发着直接调用方法更新logback配置。
doConfigure方法可以设置logback的配置,参数为配置文件的位置,也可以是配置文件的文件流。
接下来要做的是,什么时候触发logback配置的更新。
这里我使用了当当出品的config-toolkit作为配置中心。
config-toolkit提供了观察者模式实现,当配置项更新的时候,触发观察者执行动作。
当然,其他的开源配置中心,比如携程的apollo也提供了当配置发生变化的时候的回调。
当配置项更新的时候,执行两个动作:
根据更新的配置项,获取logback配置的字符串
使用新的logback配置字符串配置logback
logback配置的字符串基于freemarker模板,使用新的配置项的值,更新freemarker的占位符模板。
方案中使用的freemarker模板如下:
此模板只有两类占位符:
${logback_logger_root_lever}用于定义root的日志级别
logconfigs用于定义package或者class的日志级别
logback的日志级别是树状结构的,如果子类没有定义日志级别的话,就使用父类的日志级别,root日志级别是所有子类的日志级别。
一个日志级别配置如下图所示:
其中logback.logger.root.lever的配置值会替换掉${logback_logger_root_lever}占位符,这里占位符不用${logback.logger.root.lever}是因为如果这么写,freemark会把logback当成一个对象,寻找一个logger的属性值。
以lever为前缀的配置项会替换掉模板中的#list logconfigs。