繁体   English   中英

如何在ActiveMQ中使用log4j2 JMSAppender

[英]How to use log4j2 JMSAppender with ActiveMQ

我正在努力编写一个简单的POC程序来将消息记录到队列中。 我发现的所有教程和问答( 此处此处 )均使用log4j 1.2版,并且它们将消息放入主题而不是队列中。 我的要求是登录到队列。

我遵循了官方网站上提到的文档,但无法使其正常运行。

我的类路径上有log4j2和ActiveMQ JAR,我创建了队列“ logQueue”,能够在ActiveMQ Web控制台中看到该队列,当我尝试执行该程序来编写日志时,出现以下错误:

ERROR Error creating JmsManager using ConnectionFactory [ConnectionFactory] and Destination [logQueue]. javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)

显然看起来像是一些JNDI问题,但无法弄清楚是什么。 根据log4j 1.2教程,我还将jndi.properties文件添加到类路径中,其值是

queue.logQueue=logQueue

但这显然没有帮助。 下面是我的log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <JMS name="jmsQueue" destinationBindingName="logQueue"
         factoryBindingName="ConnectionFactory"
         providerURL="tcp://localhost:61616"/>
  </Appenders>
  <Loggers>
    <Root level="all">
      <AppenderRef ref="jmsQueue"/>
    </Root>
  </Loggers>
</Configuration>

谢谢 !

factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory"添加到JMS元素即可解决此问题。

log4j2.xml中的最后一个JMS元素如下所示:

<JMS name="jmsQueue" destinationBindingName="logQueue"
        factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory"
        factoryBindingName="ConnectionFactory"
        providerURL="tcp://localhost:61616"/>

在追加程序初始化期间出现错误,因此我尝试编写自己的脚本,而不使用现有的xml配置。

依赖版本:

  • ActiveMQ 5.12.1客户端
  • log4j的核 - 2.5
  • SLF4J-1.7.12

Java类:

复制课程并将其放在项目中的任何位置,

package com.towersoft.eagleserver;

import java.io.Serializable;

import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;


@Plugin(name = "JMSQueueAppender", category = "Core", elementType = "appender", printObject = true)
public class JMSQueueAppender extends AbstractAppender {

//    private static Logger logger = Logger.getLogger("JMSQueueAppender");
    private String brokerUri = "failover://tcp://localhost:61616";
    private String queueName = "logQueue";
    Session session;

    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(this.brokerUri);
    javax.jms.Connection connection;
    Destination destination;
    MessageProducer producer;


    private void init() {
        try {

            connection = connectionFactory.createConnection();
            connection.start();
            // Create a Session
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createQueue(this.queueName);
            producer = session.createProducer(destination);
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected JMSQueueAppender(String name, Filter filter,
            Layout<? extends Serializable> layout, final boolean ignoreExceptions) {
        super(name, filter, layout, ignoreExceptions);
        init();
    }

    @Override
    public void append(LogEvent le) {
        try {
            if (connection == null) {
                init();
            }
            TextMessage message = session.createTextMessage(le.getMessage().getFormattedMessage());
            // Tell the producer to send the message
            producer.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void stop() {
        super.stop(); 
        try {
            session.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PluginFactory
    public static JMSQueueAppender createAppender(
            @PluginAttribute("name") String name,
            @PluginElement("Layout") Layout<? extends Serializable> layout,
            @PluginElement("Filter") final Filter filter) {
        if (name == null) {
            LOGGER.error("No name provided for MyCustomAppenderImpl");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new JMSQueueAppender(name, filter, layout, true);
    }
}

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <JMSQueueAppender name="jmsQueue"/>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="jmsQueue"/>
        </Root>
        <Logger name="org.quartz" level="ERROR"/>
        <Logger name="com.zaxxer" level="ERROR"/>
        <Logger name="org.apache.activemq" level="ERROR"/>
    </Loggers>
</Configuration>

我确实有这个问题。 通过将文件添加到我的Maven资源目录中名为jndi.properties的内容来解决...

topic.logTopic=logTopic
queue.logQueue=logQueue

显然,可以修改实际使用的名称。 就我而言,我的appender可能是...

<JMS name="jmsQueue" 
            destinationBindingName="logQueue" 
            factoryName="org.apache.activemq.jndi.ActiveMQInitialContextFactory"
            factoryBindingName="ConnectionFactory"
            providerURL="tcp://localhost:61616"
            userName="admin"
            password="admin">
            <SyslogLayout />
          </JMS>

注意:我必须修改附加程序的布局,以避免序列化错误(其他可能的值是... JSONLayout,YamlLayout,HtmlLayout等)。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM