vertx导致再次创建log4j2自定义追加程序

时间:2020-11-04 14:23:34

标签: plugins log4j2 vert.x

我有一个客户附加程序:

package com.test.logging;

@Plugin(
        name = "xAppender",
        category = Core.CATEGORY_NAME,
        elementType = Appender.ELEMENT_TYPE)
public class XAppender extends AbstractAppender {

protected XAppender (...) {
   super(...)
   // some logging to see how many times constructor is called
}

@PluginFactory
public static XAppender createAppender(...) {}

@Override
public void append(LogEvent logEvent) {}

}

和配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" packages="com.microsoft.applicationinsights.log4j.v2, no.test.logging">
    <Appenders>
        <XAppender name="xAppender"
        </XAppender>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="xAppender"/>
        </Root>
    </Loggers>
</Configuration>

当我在intelliJ中运行代码时,appender构造函数仅被调用一次。如果我使用maven(尝试了maven程序集和shade插件)构建了一个jar,然后运行它,则构造函数(@PluginFactory createAppender)会被调用两次。仅当我初始化一个vertx实例时才会发生这种情况。为什么会发生这种情况?

编辑:我删除了@PluginFactory批注,并且可以看到以下堆栈跟踪。似乎log4j2和io.vertx.core.logging框架都调用了它:

2020-11-05 12:38:20,932 main ERROR Unable to invoke factory method in class com.test.logging.XAppender for element XAppender: java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:234)
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:134)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1002)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:942)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:934)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:552)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:241)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:288)
        at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:618)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:691)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:708)
        at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:263)
        at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
        at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
        at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
        at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:602)
        at no.Test.main<clinit>(Test.java:26)

并且:

2020-11-05 12:38:21,075 main ERROR Unable to invoke factory method in class com.test.logging.XAppender for element TcAppender: java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:234)
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:134)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1002)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:942)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:934)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:552)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:241)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:288)
        at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:618)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:691)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:708)
        at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:263)
        at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:243)
        at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
        at org.apache.logging.log4j.LogManager.getContext(LogManager.java:174)
        at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:669)
        at io.vertx.core.logging.Log4j2LogDelegate.<init>(Log4j2LogDelegate.java:31)
        at io.vertx.core.logging.Log4j2LogDelegateFactory.createDelegate(Log4j2LogDelegateFactory.java:28)
        at io.vertx.core.logging.LoggerFactory.getLogger(LoggerFactory.java:74)
        at io.vertx.core.logging.LoggerFactory.getLogger(LoggerFactory.java:67)
        at io.vertx.core.impl.AddressResolver.<clinit>(AddressResolver.java:37)
        at io.vertx.core.dns.AddressResolverOptions.<clinit>(AddressResolverOptions.java:80)
        at io.vertx.core.VertxOptions.<init>(VertxOptions.java:183)
        at io.vertx.core.impl.VertxFactoryImpl.vertx(VertxFactoryImpl.java:27)
        at io.vertx.core.Vertx.vertx(Vertx.java:75)
        at no.Test.main(Test.java:33)

编辑:

我找到了这个问题,但是我不确定潜在的问题:

似乎Vertx.vertx()创建了自己的LoggerContext。从IntelliJ启动项目时,Log4j2似乎了解这一点,并且默认情况下使用以下上下文使用相同的上下文: LogManager.getLogger(ABC.class);或LogManager.getContext(false).getLogger(ABC.class.getName());

当项目以.jar执行时,默认情况下,Log4j2不会获得由Vertx初始化的LoggerContext。可以使用LogManager.getContext(true).getLogger(ABC.class.getName());

修复此问题。

注意:在IntelliJ中运行时使用getContext(true)也会导致Log4j2无法获得相同的ContextObject,因此应根据环境(例如IntelliJ或.jar)设置布尔值

注意:在上述两种情况下,Vertx初始化后都会调用记录器。

0 个答案:

没有答案