Skip to content

Instantly share code, notes, and snippets.

@mdaniel
Created September 26, 2014 22:25
Show Gist options
  • Save mdaniel/1290c66822f7279f7e40 to your computer and use it in GitHub Desktop.
Save mdaniel/1290c66822f7279f7e40 to your computer and use it in GitHub Desktop.
StormTopology to graphviz dot format
package com.radius.kafkastorm;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Map;
import backtype.storm.generated.Bolt;
import backtype.storm.generated.ComponentObject;
import backtype.storm.generated.GlobalStreamId;
import backtype.storm.generated.Grouping;
import backtype.storm.generated.SpoutSpec;
import backtype.storm.generated.StormTopology;
/**
* Returns a <tt>graphviz</tt> compatible string representing the provided
* {@linkplain backtype.storm.generated.StormTopology}.
* It is accurate as of
* <a href="https://github.com/apache/storm/tree/v0.9.2-incubating">0.9.2-incubating</a>.
* This is the transliteration of <a href="https://github.com/schleyfox/storm-test/blob/master/src/clj/storm/test/visualization.clj"
* >visualization.clj</a>.
*/
public class Visualization
{
public static final String[] COLORS = new String[] {
"red", "orange", "yellow", "green", "blue", "indigo", "violet"
};
public static String topologyToDot(StormTopology topo) {
final Map<String, SpoutSpec> spouts = topo.get_spouts();
final Map<String, Bolt> bolts = topo.get_bolts();
return String.format("digraph Topology {%n" +
"%s" +
"%s" +
"%s" +
"%n" +
"}%n",
labelSpouts(spouts),
labelBolts(bolts),
drawConnections(bolts));
}
private static String labelSpouts(final Map<String, SpoutSpec> spouts) {
final StringBuilder sb = new StringBuilder();
for (final String id : spouts.keySet()) {
final SpoutSpec spout = spouts.get(id);
sb.append(String.format(
" \"%s\" [%s,shape=box];%n",
id, labelNode(id, spout)));
}
return sb.toString();
}
private static String labelBolts(final Map<String, Bolt> bolts) {
final StringBuilder sb = new StringBuilder();
for (final String id : bolts.keySet()) {
final Bolt bolt = bolts.get(id);
sb.append(String.format(
" \"%s\" [%s];%n",
id, labelNode(id, bolt)));
}
return sb.toString();
}
private static String labelNode(String id, Bolt b) {
return labelNode(id, b.get_bolt_object());
}
private static String labelNode(String id, SpoutSpec s) {
return labelNode(id, s.get_spout_object());
}
private static String labelNode(String id, ComponentObject co) {
final byte[] java_bytes = co.get_serialized_java();
assert null != java_bytes;
final Object javaO;
try {
javaO = new ObjectInputStream(new ByteArrayInputStream(java_bytes)).readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
return String.format("label=\"%s (%s)\"", id,
null == javaO ? "NULL": javaO.getClass().getName()
.replaceAll(".*\\.([^\\.]+)", "$1"));
}
private static String drawConnections(final Map<String, Bolt> bolts) {
final StringBuilder sb = new StringBuilder();
for (final String id : bolts.keySet()) {
final Bolt bolt = bolts.get(id);
final Map<GlobalStreamId, Grouping> inputs = bolt.get_common().get_inputs();
for (final GlobalStreamId from : inputs.keySet()) {
final Grouping grouping = inputs.get(from);
final String fromId = from.get_componentId();
final String streamId = from.get_streamId();
sb.append(String.format(" \"%s\" -> \"%s\" [%s%s];%n",
fromId, id,
"default".equals(streamId)
? ""
: String.format(
"color=%s,",
COLORS[new java.util.Random().nextInt(COLORS.length)]),
labelConnection(streamId, grouping)));
}
}
return sb.toString();
}
private static String labelConnection(String streamId, Grouping grouping) {
final String fieldName = grouping.getSetField().getFieldName();
final String groupingStr;
if ("fields".equals(fieldName)) {
groupingStr = String.valueOf(grouping.get_fields());
} else {
groupingStr = fieldName;
}
final String streamName = "default".equals(streamId)
? ""
: String.format(" \\\"%s\\\"", streamId);
return String.format("label=\"%s%s\"",
groupingStr.replaceAll("\"", "\\\""), streamName);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment