Spring-兔子使用log4j2 AmqpAppender

Spring-rabbit use log4j2 AmqpAppender

库版本

软件版本:spring-兔1.7.1.RELEASE

log4j2 : 2.8.2

slf4j : 1.7.7

log4j2 配置

<appenders>
    <console name="console" target="SYSTEM_OUT">
        <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
    </console>
    <!--<Kafka name="Kafka" topic="log-test">-->
        <!--<PatternLayout pattern="%date %message"/>-->
        <!--<Property name="bootstrap.servers">192.168.3.166:9090,192.168.3.166:9091,192.168.3.166:9092</Property>-->
    <!--</Kafka>-->
    <RabbitMQ name="rabbitmq_logdata_tojson"
              host="${sys:rabbitmq_host}"
              port="${sys:rabbitmq_port}"
              user="${sys:rabbitmq_user}"
              password="${sys:rabbitmq_password}"
              virtualHost="/"
              exchange="${sys:rabbitmq_exchange}"
              exchangeType="${sys:rabbitmq_exchangeType}"
              declareExchange="true"
              durable="true"
              autoDelete="false"
              applicationId="${sys:rabbitmq_qname_4logdata.json}"
              routingKeyPattern="${sys:rabbitmq_qname_4logdata.json}"
              contentType="text/plain"
              contentEncoding="${sys:log4j2_charset}"
              generateId="false"
              deliveryMode="NON_PERSISTENT"
              charset="${sys:log4j2_charset}"
              senderPoolSize="1" maxSenderRetries="5">
    </RabbitMQ>

    <!--flume appender的配置,此处采用Avro类型 -->
    <!--<Flume name="flume_logdata_in" compress="false" type="Avro" >-->
        <!--<Agent host="192.168.2.111" port="4444"/>-->
    <!--</Flume>-->

</appenders>

<loggers>

    <logger name="${sys:rabbitmq_qname_4logdata.json}" level="info">
        <appender-ref ref="rabbitmq_logdata_tojson"/>
    </logger>

    <!--<logger name="${sys:rabbitmq_qname_4logdata}" level="info">-->
        <!--<appender-ref ref="rabbitmq_logdata_tobyte"/>-->
    <!--</logger>-->

    <root level="debug">
        <appender-ref ref="console"/>
        <!--<appender-ref ref="Kafka"/>-->
    </root>
</loggers>

Java代码

private static final Logger writeQueueLog= LoggerFactory.getLogger(System.getProperty("rabbitmq_qname_4logdata.json"));
writeQueueLog.info(jsonObject.toString());

System.properties

rabbitmq_qname_4logdata.json=user.behavior.countmessage.queue
rabbitmq_qname_4logdata=user.behavior.logdatainfo.queue

当我使用 AMQPAppender 向 rabbitmq 发送消息时,总是有一些其他记录器消息。

我调试了APQPAppender的源代码,当方法"append"被调用时,所有的事件都是正确的。但是Sender是运行,总是有一些来自其他logger的事件,最后,消息计数是正确的。

然后,我将附加队列更改为 String,如下所示:private final LinkedBlockingQueue<String> eventsStrs = new LinkedBlockingQueue<String>();,并在方法 append() 中添加数据,

我看到所有值都是正确的,但事件中的值有一些错误信息。

我猜这个事件已经在其他地方改变了。

我不知道,你能帮我吗?

我在 Log4J2 中找到了这段代码...

    if (LOG_EVENT_FACTORY == null) {
        LOG_EVENT_FACTORY = Constants.ENABLE_THREADLOCALS
                ? new ReusableLogEventFactory()
                : new DefaultLogEventFactory();
    }

如果你 运行 和 -Dlog4j2.enable.threadlocals=false 它将是线程安全的。

我将向 Spring appender 添加一个选项以在调用线程上发送消息而不是传递给另一个线程,这将使使用 ReusableLogEventFactory 安全。

您还可以使用 Log4jLogEventFactory 显式设置事件工厂。

请参阅系统属性 here