首页 > 解决方案 > logback 创建 appender 的新实例

问题描述

我使用 LogBack,我有几个 Logger。我创建了一个自定义附加程序:

public class LogListenerAppender extends AppenderBase<ILoggingEvent> {

    private List<LogListener> listeners;

    public LogListenerAppender() {
        listeners = new ArrayList<>();
    }

    public void addListener(LogListener listener){
        listeners.add(listener);
        System.out.println("Current listener: " + listeners.size());
    }

    /**
     * Send the LogEvent to all Listeners
     * @param eventObject the LogEventObject
     */
    @Override
    protected void append(ILoggingEvent eventObject) {
        for(LogListener listener : listeners){
            listener.receiveLogMessage(eventObject);
        }
    }
}

这个 appender 是为 Logger 添加监听器来捕获 Log 消息。

现在在我的 logback.xml 文件中,我将 Appender 创建为 LISTENER

<!--Custom Listener Appender-->
<appender name="LISTENER" class="path.to.LogListenerAppender"/>

还有一些记录器:

<logger name="TestLogger">
    <appender-ref ref="LISTENER" />
</logger>

<logger name="MainLogger">
    <appender-ref ref="LISTENER" />
</logger>

在代码中,我将 LogListener 添加到 Logger:

public static void main(String[] args){
    Logger testLogger = LoggerFactory.getLogger("TestLogger");
    Logger mainLogger = LoggerFactory.getLogger("MainLogger");

    addListenerToLogger(testLogger, new LogListener(Level.TRACE) {
        @Override
        public void log(String message, long timestamp) {
            System.out.println("TEST LOG: " + message);
        }
    });
    addListenerToLogger(mainLogger, new LogListener(Level.TRACE) {
        @Override
        public void log(String message, long timestamp) {
            System.out.println("MAIN LOG: " + message);
        }
    });
    testLogger.info("Hello");
}

private static void addListenerToLogger(Logger logger, LogListener loglistener){
    ch.qos.logback.classic.Logger log = (ch.qos.logback.classic.Logger) logger;
    LogListenerAppender appender = (LogListenerAppender)log.getAppender("LISTENER");
    appender.addListener(loglistener);
}

所需的输出是:

测试日志:你好

但输出是:

测试日志:你好
主日志:你好

System.out.println("Current listener: " + listeners.size());在 LogListenerAppender 中打印 2。

我现在的问题是 Logback 对所有使用<appender-ref ref="LISTENER"/>.

但是我需要为每个 Logger 一个新的 LogListenerAppender。如何配置他每次创建新实例时创建的 logBack?

我的想法是为每个记录器创建附加程序,例如:

<appender name="LISTENER1" class="path.to.LogListenerAppender"/>
<appender name="LISTENER2" class="path.to.LogListenerAppender"/>
//etc...
<logger name="TestLogger">
    <appender-ref ref="LISTENER1" />
</logger>

<logger name="MainLogger">
    <appender-ref ref="LISTENER2" />
</logger>
//etc...

但我希望它存在一种更简单的方法

标签: javalogback

解决方案


您可以在此处查看代码中出现这种情况的原因:

LogListenerAppender appender = (LogListenerAppender)log.getAppender("LISTENER");

您的代码只会获取您在内存中创建的任何附加程序,并标记为“LISTENER”。该侦听器列表中的所有内容都将侦听来自带有侦听器标记的附加程序的任何事件。

也许尝试像这样向您的添加侦听器方法添加一个字符串:

private static void addListenerToLogger(Logger logger, LogListener loglistener, String appenderRef){
    ch.qos.logback.classic.Logger log = (ch.qos.logback.classic.Logger) logger;
    LogListenerAppender appender = (LogListenerAppender)log.getAppender(appenderRef);
    appender.addListener(loglistener);
}

这样,您可以将适当的 appender ref(即“LISTENER1”)传递给该方法以检索适当的 appender。

选择适当的参考也是值得的,即;

<logger name="TestLogger">
    <appender-ref ref="TEST" />
</logger>

<logger name="MainLogger">
    <appender-ref ref="MAIN" />
</logger>

为了可读性和可维护性,但这是一种风格选择,而不是技术决策


推荐阅读