ActiveMQ 日志配置

ActiveMQ默认的日志输出等级都是 INFO,生产环境INFO基本上没有问题,但是当我们还不熟悉环境活在 我们程序还不够稳定的时候,更详细的日志是我们排查问题的好帮手,修改 conf/log4j.properties, 可以将以下内容直接替换原来的配置。

# 默认的输出到文件的日志配置(等级为INFO)
# log4j.rootLogger=INFO, console, logfile
# 现修改输出到文件的日志等级为 DEBUG
log4j.rootLogger=DEBUG, console, logfile
log4j.logger.org.apache.activemq.spring=WARN
log4j.logger.org.apache.activemq.web.handler=WARN
log4j.logger.org.springframework=WARN
log4j.logger.org.apache.xbean=WARN
log4j.logger.org.apache.camel=INFO
log4j.logger.org.eclipse.jetty=WARN

# Console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%5p | %m%n

# 默认的输出到控制台的日志配置(等级为INFO)
# log4j.appender.console.threshold=INFO
# 现修改输出到文件的日志等级为 DEBUG
log4j.appender.console.threshold=DEBUG

# File appender
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.file=${activemq.data}/activemq.log
log4j.appender.logfile.maxFileSize=20MB
log4j.appender.logfile.maxBackupIndex=5
log4j.appender.logfile.append=true
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n

log4j.throwableRenderer=org.apache.log4j.EnhancedThrowableRenderer

###########
# Audit log
###########

log4j.additivity.org.apache.activemq.audit=false
log4j.logger.org.apache.activemq.audit=INFO, audit

log4j.appender.audit=org.apache.log4j.RollingFileAppender
log4j.appender.audit.file=${activemq.data}/audit.log
log4j.appender.audit.maxFileSize=20MB
log4j.appender.audit.maxBackupIndex=5
log4j.appender.audit.append=true
log4j.appender.audit.layout=org.apache.log4j.PatternLayout
log4j.appender.audit.layout.ConversionPattern=%-5p | %m | %t%n

ActiveMQ 状态查询

监控 activemq 各个queuetopic的状态,包括剩余数据量,消费者数量,出队数量,

需要activemq支持远程监控,配置如下:

修改conf目录下的activemq.xml文件的 managementContext 节点,

配置 connectorHost可以不配,配了好像不起作用,后续研究。

<managementContext>  
			<managementContext createConnector="true" connectorHost="10.0.0.134" connectorPort="1099" 				connectorPath="/jmxrmi" jmxDomainName="org.apache.activemq"/>  
		</managementContext>  

Java 代码

/**
	 * 
	 * 监控 ActiveMQ
	 * 
	 * @param ip
	 * @param connectorPort
	 * @param connectorPath
	 * @param jmxDomainName
	 *            必须与activemq.xml中的jmxDomainName一致
	 * @param brokerName
	 *            必须与activemq.xml中 broker 节点的 brokerName一致
	 * @throws IOException
	 * @throws MalformedObjectNameException
	 */
	public static List<MQModel> monitor(String ip, int connectorPort, String connectorPath, String jmxDomainName,
			String brokerName)
			throws IOException, MalformedObjectNameException {

		List<MQModel> models = new ArrayList<MQModel>();

		JMXServiceURL url = new JMXServiceURL(
				String.format("service:jmx:rmi:///jndi/rmi://%s:%s%s", ip, connectorPort, connectorPath));
		JMXConnector connector = JMXConnectorFactory.connect(url, null);
		connector.connect();

		MBeanServerConnection connection = connector.getMBeanServerConnection();

		ObjectName name = new ObjectName(jmxDomainName + ":BrokerName=" + brokerName + ",Type=Broker");
		BrokerViewMBean mBean = (BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, name,
				BrokerViewMBean.class, true);

		for (ObjectName topicName : mBean.getTopics()) {
			TopicViewMBean topice = (TopicViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection,
					topicName, TopicViewMBean.class, true);

			TopicModel topicModel = new TopicModel(ip, topice.getName(), topice.getQueueSize(),
					topice.getConsumerCount(), topice.getDequeueCount());

			models.add(topicModel);
		}

		for (ObjectName queueName : mBean.getQueues()) {
			QueueViewMBean queueMBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection,
					queueName, QueueViewMBean.class, true);

			QueueModel queue = new QueueModel(ip, queueMBean.getName(), queueMBean.getQueueSize(),
					queueMBean.getConsumerCount(), queueMBean.getDequeueCount());

			models.add(queue);
		}

		connector.close();

		return models;

	}
  
  
  
  public abstract class MQModel {

	// IP
	private String ip;

	// 队列名称或广播名称
	private String name;
	// 队列或广播的剩余数据量
	private long queueSize;
	// 消费者数量
	private long consumerCount;
	// 出队数量
	private long dequeueCount;
	// 类型:queue 或 topic
	private String type;

	public MQModel(String type) {
		this.type = type;
	}

	public MQModel(String ip, String type, String name, long queueSize, long consumerCount, long dequeueCount) {
		this.ip = ip;
		this.type = type;
		this.name = name;
		this.queueSize = queueSize;
		this.consumerCount = consumerCount;
		this.dequeueCount = dequeueCount;

	}

	public String toString() {
		return String.format("type:%s,name:%s,size:%s,consumerCount:%s,dequeueCount:%s", type, name, queueSize,
				consumerCount, dequeueCount);
	}
  
  // get and set
  
  }
  
  
  public class QueueModel extends MQModel {

	public QueueModel() {
		super("queue");
	}

	public QueueModel(String ip, String name, long queueSize, long consumerCount, long dequeueCount) {
		super(ip, "queue", name, queueSize, consumerCount, dequeueCount);
	}
  
  public class TopicModel extends MQModel {

	public TopicModel() {
		super("topic");
	}

	public TopicModel(String ip, String name, long queueSize, long consumerCount, long dequeueCount) {
		super(ip, "topic", name, queueSize, consumerCount, dequeueCount);
	}
}


}