Skip to content

Commit

Permalink
[SPARK-45480][SQL][UI] Selectable Spark Plan Node on UI
Browse files Browse the repository at this point in the history
### What changes were proposed in this pull request?

This PR introduces selectable animation for Spark SQL Plan Node On UI, which lights up the selected node and its linked nodes and edges.

### Why are the changes needed?

Better UX for SQL plan visualization and debugging. Especially for large queries, users can now concentrate on the current node and its nearest neighbors to get a better understanding of node lineage.

### Does this PR introduce _any_ user-facing change?

Yes, let's see the video.

### How was this patch tested?

https://github.com/apache/spark/assets/8326978/f5ba884c-acce-46b8-8568-3ead55c91d4f

### Was this patch authored or co-authored using generative AI tooling?

no

Closes apache#43307 from yaooqinn/SPARK-45480.

Authored-by: Kent Yao <yao@apache.org>
Signed-off-by: Kent Yao <yao@apache.org>
  • Loading branch information
yaooqinn committed Oct 11, 2023
1 parent 64ac59d commit 305db07
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,21 @@
.job-url {
word-wrap: break-word;
}

#plan-viz-graph svg g.node rect.selected {
fill: #E25A1CFF;
stroke: #317EACFF;
stroke-width: 2px;
}

#plan-viz-graph svg g.node rect.linked {
fill: #FFC106FF;
stroke: #317EACFF;
stroke-width: 2px;
}

#plan-viz-graph svg path.linked {
fill: #317EACFF;
stroke: #317EACFF;
stroke-width: 2px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function renderPlanViz() {
.attr("ry", "5");

setupLayoutForSparkPlanCluster(g, svg);
setupSelectionForSparkPlanNode(g);
setupTooltipForSparkPlanNode(g);
resizeSvg(svg);
postprocessForAdditionalMetrics();
Expand Down Expand Up @@ -269,3 +270,45 @@ function togglePlanViz() { // eslint-disable-line no-unused-vars
planVizContainer().style("display", "none");
}
}

/*
* Light up the selected node and its linked nodes and edges.
*/
function setupSelectionForSparkPlanNode(g) {
const linkedNodes = new Map();
const linkedEdges = new Map();

g.edges().forEach(function (e) {
const edge = g.edge(e);
const from = g.node(e.v);
const to = g.node(e.w);
collectLinks(linkedNodes, from.id, to.id);
collectLinks(linkedNodes, to.id, from.id);
collectLinks(linkedEdges, from.id, edge.arrowheadId);
collectLinks(linkedEdges, to.id, edge.arrowheadId);
});

linkedNodes.forEach((linkedNodes, selectNode) => {
d3.select("#" + selectNode).on("click", () => {
planVizContainer().selectAll(".selected").classed("selected", false);
planVizContainer().selectAll(".linked").classed("linked", false);
d3.select("#" + selectNode + " rect").classed("selected", true);
linkedNodes.forEach((linkedNode) => {
d3.select("#" + linkedNode + " rect").classed("linked", true);
});
linkedEdges.get(selectNode).forEach((linkedEdge) => {
const arrowHead = d3.select("#" + linkedEdge + " path");
arrowHead.classed("linked", true);
const arrowShaft = $(arrowHead.node()).parents("g.edgePath").children("path");
arrowShaft.addClass("linked");
});
});
});
}

function collectLinks(map, key, value) {
if (!map.has(key)) {
map.set(key, new Set());
}
map.get(key).add(value);
}

0 comments on commit 305db07

Please sign in to comment.