Repository: spark Updated Branches: refs/heads/master bfcaf8adc -> 65697bbea
http://git-wip-us.apache.org/repos/asf/spark/blob/65697bbe/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js ---------------------------------------------------------------------- diff --git a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js index 764dd2c..8b7b1f6 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js +++ b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js @@ -140,8 +140,6 @@ function renderDagViz(forJob) { svg.selectAll("#" + nodeId).classed("cached", true); }); - // More post-processing - drawClusterLabels(svg, forJob); resizeSvg(svg); } @@ -151,7 +149,7 @@ function renderDagVizForStage(svgContainer) { var dot = metadata.select(".dot-file").text(); var containerId = VizConstants.graphPrefix + metadata.attr("stage-id"); var container = svgContainer.append("g").attr("id", containerId); - renderDot(dot, container, StagePageVizConstants.rankSep); + renderDot(dot, container, false); // Round corners on rectangles svgContainer @@ -209,7 +207,7 @@ function renderDagVizForJob(svgContainer) { } // Actually render the stage - renderDot(dot, container, JobPageVizConstants.rankSep); + renderDot(dot, container, true); // Round corners on rectangles container @@ -231,14 +229,14 @@ function renderDagVizForJob(svgContainer) { } /* Render the dot file as an SVG in the given container. */ -function renderDot(dot, container, rankSep) { +function renderDot(dot, container, forJob) { var escaped_dot = dot .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, "\""); var g = graphlibDot.read(escaped_dot); - g.graph().rankSep = rankSep; var renderer = new dagreD3.render(); + preprocessGraphLayout(g, forJob); renderer(container, g); } @@ -251,50 +249,37 @@ function graphContainer() { return d3.select("#dag-viz-graph"); } function metadataContainer() { return d3.select("#dag-viz-metadata"); } /* - * Helper function to create draw a label for each cluster. - * - * We need to do this manually because dagre-d3 does not support labeling clusters. - * In general, the clustering support for dagre-d3 is quite limited at this point. + * Helper function to pre-process the graph layout. + * This step is necessary for certain styles that affect the positioning + * and sizes of graph elements, e.g. padding, font style, shape. */ -function drawClusterLabels(svgContainer, forJob) { - var clusterLabelSize, stageClusterLabelSize; +function preprocessGraphLayout(g, forJob) { + var nodes = g.nodes(); + for (var i = 0; i < nodes.length; i++) { + var isCluster = g.children(nodes[i]).length > 0; + if (!isCluster) { + var node = g.node(nodes[i]); + if (forJob) { + // Do not display RDD name on job page + node.shape = "circle"; + node.labelStyle = "font-size: 0px"; + } else { + node.labelStyle = "font-size: 12px"; + } + node.padding = "5"; + } + } + // Curve the edges + var edges = g.edges(); + for (var j = 0; j < edges.length; j++) { + edges[j].lineInterpolate = "basis"; + } + // Adjust vertical separation between nodes if (forJob) { - clusterLabelSize = JobPageVizConstants.clusterLabelSize; - stageClusterLabelSize = JobPageVizConstants.stageClusterLabelSize; + g.graph().rankSep = JobPageVizConstants.rankSep; } else { - clusterLabelSize = StagePageVizConstants.clusterLabelSize; - stageClusterLabelSize = StagePageVizConstants.stageClusterLabelSize; + g.graph().rankSep = StagePageVizConstants.rankSep; } - svgContainer.selectAll("g.cluster").each(function() { - var cluster = d3.select(this); - var isStage = cluster.attr("id").indexOf(VizConstants.stageClusterPrefix) > -1; - var labelSize = isStage ? stageClusterLabelSize : clusterLabelSize; - drawClusterLabel(cluster, labelSize); - }); -} - -/* - * Helper function to draw a label for the given cluster element based on its name. - * - * In the process, we need to expand the bounding box to make room for the label. - * We need to do this because dagre-d3 did not take this into account when it first - * rendered the bounding boxes. Note that this means we need to adjust the view box - * of the SVG afterwards since we shifted a few boxes around. - */ -function drawClusterLabel(d3cluster, fontSize) { - var cluster = d3cluster; - var rect = d3cluster.select("rect"); - rect.attr("y", toFloat(rect.attr("y")) - fontSize); - rect.attr("height", toFloat(rect.attr("height")) + fontSize); - var labelX = toFloat(rect.attr("x")) + toFloat(rect.attr("width")) - fontSize / 2; - var labelY = toFloat(rect.attr("y")) + fontSize * 1.5; - var labelText = cluster.attr("name").replace(VizConstants.clusterPrefix, ""); - cluster.append("text") - .attr("x", labelX) - .attr("y", labelY) - .attr("text-anchor", "end") - .style("font-size", fontSize + "px") - .text(labelText); } /* @@ -444,7 +429,7 @@ function addTooltipsForRDDs(svgContainer) { if (tooltipText) { node.select("circle") .attr("data-toggle", "tooltip") - .attr("data-placement", "right") + .attr("data-placement", "bottom") .attr("title", tooltipText) } }); http://git-wip-us.apache.org/repos/asf/spark/blob/65697bbe/core/src/main/scala/org/apache/spark/ui/UIUtils.scala ---------------------------------------------------------------------- diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala index 6a0f5c5..441c97d 100644 --- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala +++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala @@ -360,7 +360,7 @@ private[spark] object UIUtils extends Logging { { graphs.map { g => <div class="stage-metadata" stage-id={g.rootCluster.id} style="display:none"> - <div class="dot-file">{RDDOperationGraph.makeDotFile(g, forJob)}</div> + <div class="dot-file">{RDDOperationGraph.makeDotFile(g)}</div> { g.incomingEdges.map { e => <div class="incoming-edge">{e.fromId},{e.toId}</div> } } { g.outgoingEdges.map { e => <div class="outgoing-edge">{e.fromId},{e.toId}</div> } } { http://git-wip-us.apache.org/repos/asf/spark/blob/65697bbe/core/src/main/scala/org/apache/spark/ui/scope/RDDOperationGraph.scala ---------------------------------------------------------------------- diff --git a/core/src/main/scala/org/apache/spark/ui/scope/RDDOperationGraph.scala b/core/src/main/scala/org/apache/spark/ui/scope/RDDOperationGraph.scala index b470aaa..25d5c6f 100644 --- a/core/src/main/scala/org/apache/spark/ui/scope/RDDOperationGraph.scala +++ b/core/src/main/scala/org/apache/spark/ui/scope/RDDOperationGraph.scala @@ -158,54 +158,32 @@ private[ui] object RDDOperationGraph extends Logging { * * For the complete DOT specification, see http://www.graphviz.org/Documentation/dotguide.pdf. */ - def makeDotFile(graph: RDDOperationGraph, forJob: Boolean): String = { + def makeDotFile(graph: RDDOperationGraph): String = { val dotFile = new StringBuilder dotFile.append("digraph G {\n") - dotFile.append(makeDotSubgraph(graph.rootCluster, forJob, indent = " ")) - graph.edges.foreach { edge => - dotFile.append(s""" ${edge.fromId}->${edge.toId} [lineInterpolate="basis"];\n""") - } + dotFile.append(makeDotSubgraph(graph.rootCluster, indent = " ")) + graph.edges.foreach { edge => dotFile.append(s""" ${edge.fromId}->${edge.toId};\n""") } dotFile.append("}") val result = dotFile.toString() logDebug(result) result } - /** - * Return the dot representation of a node in an RDDOperationGraph. - * - * On the job page, is displayed as a small circle without labels. - * On the stage page, it is displayed as a box with an embedded label. - */ - private def makeDotNode(node: RDDOperationNode, forJob: Boolean): String = { - val label = s"${node.name} (${node.id})" - if (forJob) { - s"""${node.id} [label="$label" shape="circle" padding="5" labelStyle="font-size: 0"]""" - } else { - s"""${node.id} [label="$label" padding="5" labelStyle="font-size: 12px"]""" - } + /** Return the dot representation of a node in an RDDOperationGraph. */ + private def makeDotNode(node: RDDOperationNode): String = { + s"""${node.id} [label="${node.name} (${node.id})"]""" } /** Return the dot representation of a subgraph in an RDDOperationGraph. */ - private def makeDotSubgraph( - cluster: RDDOperationCluster, - forJob: Boolean, - indent: String): String = { + private def makeDotSubgraph(cluster: RDDOperationCluster, indent: String): String = { val subgraph = new StringBuilder - // TODO: move specific graph properties like these to spark-dag-viz.js - val paddingTop = if (forJob) 10 else 20 subgraph.append(indent + s"subgraph cluster${cluster.id} {\n") subgraph.append(indent + s""" label="${cluster.name}";\n""") - // If there are nested clusters, add some padding - // Do this for the stage page because we use bigger fonts there - if (cluster.childClusters.nonEmpty) { - subgraph.append(indent + s""" paddingTop="$paddingTop";\n""") - } cluster.childNodes.foreach { node => - subgraph.append(indent + s" ${makeDotNode(node, forJob)};\n") + subgraph.append(indent + s" ${makeDotNode(node)};\n") } cluster.childClusters.foreach { cscope => - subgraph.append(makeDotSubgraph(cscope, forJob, indent + " ")) + subgraph.append(makeDotSubgraph(cscope, indent + " ")) } subgraph.append(indent + "}\n") subgraph.toString() --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
