我正在构建一个用于管理logback记录器级别和更改appender的管理UI。我知道我可以使用以下代码找到添加到某个记录器的所有appender:
private Map<String, Appender<ILoggingEvent>> getAppendersMap() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Map<String, Appender<ILoggingEvent>> appendersMap = new HashMap<>();
for (Logger logger : loggerContext.getLoggerList()) {
Iterator<Appender<ILoggingEvent>> appenderIterator = logger.iteratorForAppenders();
while (appenderIterator.hasNext()) {
Appender<ILoggingEvent> appender = appenderIterator.next();
if (!appendersMap.containsKey(appender.getName())) {
appendersMap.put(appender.getName(), appender);
}
}
}
return appendersMap;
}
问题是我是否以logback.xml
为例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="10 minutes">
<appender name="writeToConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%date{yyyy-MM-dd;HH:mm:ss.SSS} %-11p: %40.40c: %X{tablist}%m %n
</pattern>
</encoder>
</appender>
<appender name="NOPAppender" class="ch.qos.logback.core.helpers.NOPAppender" />
<root>
<level value="INFO"/>
<appender-ref ref="writeToConsole"/>
</root>
</configuration>
NOPAppender
不附加到任何记录器,因此方法getAppendersMap()
找不到。
答案 0 :(得分:2)
从外部文件(logback.xml,logback-test.xml,logback.groovy等)配置自身时,Logback会像这样完成配置(这是它的功能的简略版本):
APPENDER_BAG
InterpretationContext.objectMap
appender-ref
(存在于记录器定义中),在此APPENDER_BAG
中查找引用的appender(按名称),如果存在,则将该appender添加到当前记录器您可以使用appender关联定义显式记录器:<logger name="com.x.y" level="INFO"><appender-ref ref="STDOUT"/></logger>
或使用<root/>
元素将appender与所有记录器实例相关联:<root level="INFO"><appender-ref ref="STDOUT"/></root>
。
因此,只有在配置时才知道与任何记录器无关的追加器,一旦LoggerContext
被创建,就会丢弃瞬态(APPENDER_BAG
)。这就解释了为什么getAppendersMap()
找不到您的NOOPAppender
。
我认为这里的要求就是“知道”一个appender,即使在配置时不需要它。据推测,一个appender最初可能是不需要的,但有人可以选择稍后启用。这就像你试图使用logback.xml作为某个可能想要在应用程序运行时中的某些点使用的所有appender的完整语句。为此,您必须首先在LoggerContext
中包含可选的appender,但必须使用no-op实现。这是您在问题中已经做过的事情,但您只需要将NOPAppender
添加到根上下文中。
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="NOPAppender"/>
</root>
这对正在运行的系统没有任何影响,因为appender是一个无操作系统,但由于它在LoggerContext
中被引用,它可供你管理,当然如果你想启用它,那么appender类的选择必须以编程方式更改为no-op之外的其他内容。
另一种替代方法可能是以编程方式创建一个appender,并在需要时将其添加到LoggerContext
。