我正在尝试使用log4J JMSAppender生成从Log4J通过JMS发送日志记录的概念验证。我尝试过ActiveMQ和它提供的示例。我将这个例子拆开了,并使其更通用并与多个平台兼容。
看起来我已经全部正常,因为我可以看到与ActiveMQ发生的连接,但是当我获得InitialContext时代码挂起(-Dlog4j.debug
设置ActiveMQ客户端类似乎调用log4J和加载属性,然后尝试与JMSAppender的JMS建立连接,然后代码就会挂起。我曾尝试通过仅为单个命名记录器定义appender来隔离标题为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.
答案 0 :(得分:1)
最后似乎是加载log4j配置的问题,当JMS appender建立连接时JMS配置。如果我在没有定义ActiveMQ日志级别或appender的情况下加载配置,那么一旦连接了JMSAppender就不会出现问题,那么我可以加载其他配置以允许它登录到JMS
答案 1 :(得分:0)
由于您没有提供太多详细信息(关于配置,日志,跟踪等),请问您是否遵循How do I use log4j JMS appender with ActiveMQ。如果是,如果此样本正在运行,您做了哪些更改。
答案 2 :(得分:0)
如果出现错误,您可以尝试使用AsynchAppender,它允许log4j线程在日志语句中阻止(即挂起)。我能够在AsynAppender中为JMSAppender和控制台appender执行此操作。但是,您必须将log4j.properties文件更改为log4j.xml文件配置。格式。