【问题标题】:Using the Log4J JMSAppender with ActiveMQ将 Log4J JMSAppender 与 ActiveMQ 一起使用
【发布时间】:2012-08-13 15:15:07
【问题描述】:

我正在尝试使用 log4J JMSAppender 生成从 Log4J 到 JMS 的概念验证传送日志。我已经尝试过 ActiveMQ 及其随附的示例。我将这个示例拆开,使其更通用并与多个平台兼容。

看起来我已经全部完成了,因为我可以看到与 ActiveMQ 的连接发生了,但是当我获得 InitialContext 时代码挂起(使用-Dlog4j.debug 设置 ActiveMQ 客户端类似乎调用 log4J 并加载属性,然后尝试为 JMSAppender 建立与 JMS 的连接),然后代码就挂起。我试图通过仅定义单个命名记录器的附加程序来隔离指向 JMS 的日志消息,并且 org.apache.activemq 包配置为使用 ConsoleAppender

当指向配置了 JMS 队列的 Weblogic Server 时,相同的代码也可以正常工作,但为了获得最大的兼容性,我需要尝试使其与 ActiveMQ 一起工作

我是否缺少一些“神奇”的配置来使 ActiveMQ 正常工作?

-- 到目前为止工作中的一些示例片段可以稍微充实这个问题,现在我手头有代码

log4j-jms.properties

log4j.rootLogger=INFO, stdout

## Be sure that ActiveMQ messages are not logged to 'jms' appender

log4j.logger.org.apache=ERROR, stdout
log4j.logger.javax=ERROR,stdout
log4j.logger.java=ERROR,stdout

log4j.logger.demo=DEBUG,jms

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c - %m%n

## Configure 'jms' appender. You'll also need jndi.properties file in order to make it work
log4j.appender.jms=org.apache.log4j.net.JMSAppender
log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory
log4j.appender.jms.ProviderURL=tcp://localhost:61616
log4j.appender.jms.TopicBindingName=topic.logTopic
log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory

这样做的目的是创建一个命名的 appender 'demo',并在示例代码中抓取它来记录以确保 activemq 日志不会尝试将自身发送到 JMS

代码示例。它有点乱,因为我一直在用它来尝试使事情正常进行。就目前而言,当我将它指向 Weblogic 时它会起作用,并类似地切换 log4j 配置。此代码中的对象是确保我让主题的侦听器在单独的线程中运行

NewLog4jJMSAppenderExample.java

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;

import java.util.Properties;
/**
 * A simple example of log4j jms appender in conjuction with ActiveMQ
 */
public class NewLog4jJMSAppenderExample {
    Runnable listener;
    Thread runner;

    private enum MQImplementation {
        ActiveMQ, Weblogic
    };

    public NewLog4jJMSAppenderExample() {
        // create a logTopic topic consumer

        listener = new BigEars();
        System.out.println("******* Listener Created **********");

        runner = new Thread(listener);
        runner.start();

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

    }

    public static void main(String[] args) throws Exception {
        System.out.println("******* I HAVE STARTED **********");


        new NewLog4jJMSAppenderExample();


        System.out.println("******* LOGGING **********");

        // log a message

        Logger log = Logger.getLogger("demo");
        log.error("Test log");

        Thread.sleep(100000);

        System.exit(1);

    }

    public class BigEars implements Runnable, MessageListener {
        ConnectionFactory factory;
        Connection conn;
        Session sess;
        MessageConsumer consumer;

        public BigEars() {

            MQImplementation inUse = MQImplementation.ActiveMQ;

            System.out.println("Constructing Bigears");
            try {
                Properties env = new Properties();

                switch (inUse) {

                    case Weblogic:
                        env.put(Context.INITIAL_CONTEXT_FACTORY,
                                "weblogic.jndi.WLInitialContextFactory");
                        env.put(Context.PROVIDER_URL,
                                "t3://localhost:7001");
                        break;

                    case ActiveMQ:
                        env.put(Context.INITIAL_CONTEXT_FACTORY,
                                "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
                        env.put(Context.PROVIDER_URL,
                                "tcp://localhost:61616");
                        break;
                }

                System.out.println("Initial Context");

                InitialContext jndi = new InitialContext(env);
                System.out.println("Factory");
                factory = (TopicConnectionFactory) jndi.lookup("ConnectionFactory");

                Topic theTopic = (Topic) jndi.lookup("topic.logTopic");


                System.out.println("Connection");
                conn = factory.createConnection();

                System.out.println("******* I HAVE set up and created connection **********");
                System.out.println("session");
                sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
                System.out.println("consumer");
                consumer = sess.createConsumer(theTopic);
                System.out.println("listener");
                consumer.setMessageListener(this);

                conn.start();



            } catch (JMSException jme) {
                System.out.println(jme);
            } catch (NamingException ne) {
                System.out.println(ne);
            }
        }


        public void run() {
            try {
                System.out.println("******* zzzzzzzz! **********");

                Thread.sleep(100000);
            } catch (Exception e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }

        public void onMessage(Message message) {
            try {
                try {
                    System.out.println("******* I GOT A MESSAGE **********");
                    // receive log event in your consumer
                    System.out.println(message.toString());

                    LoggingEvent event = (LoggingEvent) (((ObjectMessage) message).getObject());
                    System.out.println("Received log [" + event.getLevel() + "]: " + event.getMessage());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            } finally {

                try {
                    consumer.close();
                    sess.close();
                    conn.close();
                } catch (JMSException jme) {
                    System.out.println(jme);
                }
            }
        }

} }

设置 -Dlog4j.debug 时显示日志

******* I HAVE STARTED **********
Constructing Bigears
Initial Context
log4j: Trying to find [log4j-jms.properties] using context classloader sun.misc.Launcher$AppClassLoader@2c2bbd86.
log4j: Using URL [file:/Users/kevin/Desktop/apache-activemq-5.3.0/example/target/classes/log4j-jms.properties] for automatic log4j configuration.
log4j: Reading configuration from URL file:/Users/kevin/Desktop/apache-activemq-5.3.0/example/target/classes/log4j-jms.properties
log4j: Parsing for [root] with value=[INFO, stdout].
log4j: Level token is [INFO].
log4j: Category root set to INFO
log4j: Parsing appender named "stdout".
log4j: Parsing layout options for "stdout".
log4j: Setting property [conversionPattern] to [%d %-5p %c - %m%n].
log4j: End of parsing for "stdout".
log4j: Parsed "stdout" options.
log4j: Parsing for [org.apache] with value=[ERROR, stdout].
log4j: Level token is [ERROR].
log4j: Category org.apache set to ERROR
log4j: Parsing appender named "stdout".
log4j: Appender "stdout" was already parsed.
log4j: Handling log4j.additivity.org.apache=[null]
log4j: Parsing for [demo] with value=[DEBUG,jms].
log4j: Level token is [DEBUG].
log4j: Category demo set to DEBUG
log4j: Parsing appender named "jms".
log4j: Setting property [initialContextFactoryName] to [org.apache.activemq.jndi.ActiveMQInitialContextFactory].
log4j: Setting property [topicBindingName] to [topic.logTopic].
log4j: Setting property [topicConnectionFactoryBindingName] to [ConnectionFactory].
log4j: Setting property [providerURL] to [tcp://localhost:61616].
log4j: Getting initial context.
log4j: Looking up [ConnectionFactory]
log4j: About to create TopicConnection.
log4j: Creating TopicSession, non-transactional, in AUTO_ACKNOWLEDGE mode.

在这里它只是挂起并最终超时

【问题讨论】:

    标签: java log4j jms activemq


    【解决方案1】:

    最后似乎是加载 log4j 配置的问题,当 JMS 附加程序建立连接时 JMS 配置。如果我在没有定义 ActiveMQ 日志级别或附加程序的情况下加载配置,那么一旦附加了 JMSAppender,问题就不会发生,那么我可以加载其他配置以允许它记录到 JMS

    【讨论】:

      【解决方案2】:

      由于您没有提供太多详细信息(关于配置、日志、跟踪等),请问您是否关注了How do I use log4j JMS appender with ActiveMQ。如果是,并且如果此示例有效,您做了哪些更改。

      作为旁注,我会考虑使用 logback,而不是 log4j,它的继任者。查看它的Appenders

      【讨论】:

      • 完全遵循该示例,并使用 ActiveMQ 5.3 提供的代码,它不能开箱即用。我将看一下 logback,但我对这项工作的主要标准之一是我必须透明地处理代码中已经有 log4J 日志记录的现有代码。我确实尝试插入 slf4J,但这并没有解决 ActiveMQ 的问题。我已经在原始问题中添加了一些示例代码、配置和日志输出,因为我可以再次提交代码
      【解决方案3】:

      如果出现错误,您可以尝试使用允许 log4j 线程在日志语句上不阻塞(即挂起)的 AsynchAppender。我能够在 AsynAppender 中为 JMSAppender 和控制台附加程序执行此操作。但是,您必须将 log4j.properties 文件更改为 log4j.xml 文件配置。格式。

      【讨论】:

        猜你喜欢
        • 2012-02-23
        • 2015-07-04
        • 2014-05-17
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 2017-06-01
        • 2012-11-27
        • 2012-03-10
        相关资源
        最近更新 更多