added a visualisation plugin to render the current queue and topic hierarchies graphically

git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@389018 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
James Strachan 2006-03-27 04:33:08 +00:00
parent 90bab0fcf4
commit d84e0521ea
5 changed files with 355 additions and 2 deletions

View File

@ -0,0 +1,175 @@
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.broker.view;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.broker.region.Destination;
import org.apache.activemq.broker.region.Subscription;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ConsumerInfo;
import org.apache.activemq.filter.DestinationMap;
import org.apache.activemq.filter.DestinationMapNode;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
/**
*
* @version $Revision: $
*/
public class DestinationDotFileInterceptor extends BrokerFilter {
protected static final String ID_SEPARATOR = "_";
private String file = "ActiveMQDestinations.dot";
public DestinationDotFileInterceptor(Broker next, String file) {
super(next);
}
public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception {
Subscription answer = super.addConsumer(context, info);
//generateDestinationGraph();
return answer;
}
public Destination addDestination(ConnectionContext context, ActiveMQDestination destination) throws Exception {
Destination answer = super.addDestination(context, destination);
generateDestinationGraph();
return answer;
}
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout)
throws Exception {
super.removeDestination(context, destination, timeout);
generateDestinationGraph();
}
protected void generateDestinationGraph() throws Exception {
System.out.println("Autogenerating file: " + file);
PrintWriter writer = new PrintWriter(new FileWriter(file));
try {
generateDestinationGraph(writer);
}
finally {
writer.close();
}
}
protected void generateDestinationGraph(PrintWriter writer) throws Exception {
ActiveMQDestination[] destinations = getDestinations();
// lets split into a tree
DestinationMap map = new DestinationMap();
for (int i = 0; i < destinations.length; i++) {
ActiveMQDestination destination = destinations[i];
map.put(destination, destination);
}
// now lets navigate the tree
writer.println("digraph \"ActiveMQ Destinations\" {");
writer.println();
writer.println("node [style = \"rounded,filled\", fontname=\"Helvetica-Oblique\"];");
writer.println();
writer.println("topic_root [fillcolor = deepskyblue, label = \"Topics\" ];");
writer.println("queue_root [fillcolor = deepskyblue, label = \"Queues\" ];");
writer.println();
writer.println("subgraph queues {");
writer.println(" node [fillcolor=red]; ");
writer.println(" label = \"Queues\"");
writer.println();
printNodeLinks(writer, map.getQueueRootNode(), "queue");
writer.println("}");
writer.println();
writer.println("subgraph topics {");
writer.println(" node [fillcolor=green]; ");
writer.println(" label = \"Topics\"");
writer.println();
printNodeLinks(writer, map.getTopicRootNode(), "topic");
writer.println("}");
writer.println();
printNodes(writer, map.getQueueRootNode(), "queue");
writer.println();
printNodes(writer, map.getTopicRootNode(), "topic");
writer.println();
writer.println("}");
}
protected void printNodes(PrintWriter writer, DestinationMapNode node, String prefix) {
String path = getPath(node);
writer.print(" ");
writer.print(prefix);
writer.print(ID_SEPARATOR);
writer.print(path);
String label = path;
if (prefix.equals("topic")) {
label = "Topics";
}
else if (prefix.equals("queue")) {
label = "Queues";
}
writer.print("[ label = \"");
writer.print(label);
writer.println("\" ];");
Collection children = node.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
DestinationMapNode child = (DestinationMapNode) iter.next();
printNodes(writer, child, prefix + ID_SEPARATOR + path);
}
}
protected void printNodeLinks(PrintWriter writer, DestinationMapNode node, String prefix) {
String path = getPath(node);
Collection children = node.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
DestinationMapNode child = (DestinationMapNode) iter.next();
writer.print(" ");
writer.print(prefix);
writer.print(ID_SEPARATOR);
writer.print(path);
writer.print(" -> ");
writer.print(prefix);
writer.print(ID_SEPARATOR);
writer.print(path);
writer.print(ID_SEPARATOR);
writer.print(getPath(child));
writer.println(";");
printNodeLinks(writer, child, prefix + ID_SEPARATOR + path);
}
}
protected String getPath(DestinationMapNode node) {
String path = node.getPath();
if (path.equals("*")) {
return "root";
}
return path;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.broker.view;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerPlugin;
/**
* A <a href="http://www.graphviz.org/">DOT</a>
* file creator plugin which creates a DOT file showing the current topic & queue hierarchies.
*
* @version $Revision: $
*/
public class DestinationDotFilePlugin implements BrokerPlugin {
private String file = "ActiveMQDestinations.dot";
public Broker installPlugin(Broker broker) {
return new DestinationDotFileInterceptor(broker, file);
}
public String getFile() {
return file;
}
/**
* Sets the destination file name to create the destination diagram
*/
public void setFile(String file) {
this.file = file;
}
}

View File

@ -0,0 +1,9 @@
<html>
<head>
</head>
<body>
Broker Plugins for visualising the current system
</body>
</html>

View File

@ -0,0 +1,108 @@
/**
*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The SimpleQueueSender class consists only of a main method,
* which sends several messages to a queue.
*
* Run this program in conjunction with SimpleQueueReceiver.
* Specify a queue name on the command line when you run the
* program. By default, the program sends one message. Specify
* a number after the queue name to send that number of messages.
*/
package org.apache.activemq.demo;
// START SNIPPET: demo
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* A simple queue sender which does not use JNDI
*
* @version $Revision: 1.1 $
*/
public class DefaultQueueSender {
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
.getLog(DefaultQueueSender.class);
public static void main(String[] args) {
String uri = "tcp://localhost:61616";
String text = "Hello World!";
Connection connection = null;
QueueSession queueSession = null;
if ((args.length < 1)) {
printUsage();
System.exit(1);
}
int idx = 0;
String arg = args[0];
if (arg.equals("-uri")) {
if (args.length == 1) {
printUsage();
System.exit(1);
}
uri = args[1];
idx += 2;
}
String queueName = args[idx];
System.out.println("Connecting to: " + uri);
System.out.println("Queue name is " + queueName);
if (++idx < args.length) {
text = args[idx];
}
try {
ConnectionFactory factory = new ActiveMQConnectionFactory(uri);
connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queueName);
MessageProducer producer = session.createProducer(destination);
Message message = session.createTextMessage(text);
producer.send(message);
}
catch (JMSException e) {
log.info("Exception occurred: " + e.toString());
}
finally {
if (connection != null) {
try {
connection.close();
}
catch (JMSException e) {
}
}
}
}
protected static void printUsage() {
System.out.println("Usage: java DefaultQueueSender [-uri <connection-uri>] " + "<queue-name> [<message-body>]");
}
}
// END SNIPPET: demo

View File

@ -17,12 +17,17 @@
package org.apache.activemq.test; package org.apache.activemq.test;
import org.apache.activemq.broker.BrokerFactory; import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerPlugin;
import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.view.DestinationDotFileInterceptor;
import org.apache.activemq.broker.view.DestinationDotFilePlugin;
import org.apache.activemq.demo.DefaultQueueSender;
import java.net.URI; import java.net.URI;
/** /**
* A helper class which can be handy for running a broker in your IDE from the activemq-core module. * A helper class which can be handy for running a broker in your IDE from the
* activemq-core module.
* *
* @version $Revision$ * @version $Revision$
*/ */
@ -37,8 +42,18 @@ public class Main {
brokerURI = args[0]; brokerURI = args[0];
} }
try { try {
BrokerService broker = BrokerFactory.createBroker(new URI(brokerURI)); //BrokerService broker = BrokerFactory.createBroker(new URI(brokerURI));
BrokerService broker = new BrokerService();
broker.setPersistent(false);
broker.setUseJmx(true);
broker.setPlugins(new BrokerPlugin[] { new DestinationDotFilePlugin() });
broker.addConnector("tcp://localhost:61616");
broker.addConnector("stomp://localhost:61613");
broker.start(); broker.start();
// lets publish some messages so that there is some stuff to browse
DefaultQueueSender.main(new String[] {"Prices.Equity.IBM"});
DefaultQueueSender.main(new String[] {"Prices.Equity.MSFT"});
} }
catch (Exception e) { catch (Exception e) {
System.out.println("Failed: " + e); System.out.println("Failed: " + e);