能否覆盖Logback引入文件中定义的Appender部分配置?
背景
我负责维护一批运行在Kubernetes中的SpringBoot Java服务,所有服务均使用slf4j/logback日志框架。每个服务的源码中都有独立的logback.xml,且都会引入一份由Kubernetes ConfigMap提供的外部公共配置文件。公共配置里定义了一个包含大量属性的STDOUT ConsoleAppender,其中LoggingEventCompositeJsonEncoder编码器的stackTrace配置如下:
<stackTrace> <fieldName>exTrace</fieldName> <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter"> <maxDepthPerThrowable>10</maxDepthPerThrowable> <rootCauseFirst>false</rootCauseFirst> <maxLength>10240</maxLength> </throwableConverter> </stackTrace>
各服务可在自身logback.xml中自定义部分Logger,现在需要实现每个服务对上述stackTrace块的自定义,以下是两个问题的解答:
问题1:在include公共配置语句后直接粘贴完整的Appender定义,是否会替换基础配置中的对应Appender?
会替换。Logback加载配置文件是按顺序执行的,当遇到同名的Appender定义时,后加载的Appender实例会直接覆盖之前的。也就是说,如果公共配置里已经定义了名为STDOUT的Appender,在include之后再写一份完整的STDOUT Appender定义,最终生效的会是你后面写的这份。
问题2:是否可保留基础Logback配置,仅在服务的logback.xml中指定覆盖provider的部分属性(如stackTrace元素)?
Logback原生不支持直接“部分覆盖”编码器内的单个provider配置,因为编码器是一个完整的组件实例,一旦初始化就无法拆分修改。不过可以通过以下方式实现类似效果:
将公共配置中stackTrace的可变参数抽成Logback属性并设置默认值,每个服务在自身logback.xml中重新定义这些属性即可覆盖对应参数。
比如公共配置里修改为:
<stackTrace> <fieldName>${log.stacktrace.fieldName:exTrace}</fieldName> <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter"> <maxDepthPerThrowable>${log.stacktrace.maxDepth:10}</maxDepthPerThrowable> <rootCauseFirst>${log.stacktrace.rootCauseFirst:false}</rootCauseFirst> <maxLength>${log.stacktrace.maxLength:10240}</maxLength> </throwableConverter> </stackTrace>
然后在服务的logback.xml中,在include公共配置之前添加属性定义:
<property name="log.stacktrace.maxDepth" value="20"/> <property name="log.stacktrace.rootCauseFirst" value="true"/>
这样就能仅修改指定参数,保留公共配置的其他部分。
内容的提问来源于stack exchange,提问作者David M. Karr

