This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 305db078ff2 [SPARK-45480][SQL][UI] Selectable Spark Plan Node on UI
305db078ff2 is described below

commit 305db078ff25c3c29b222f197b3293dd84db3045
Author: Kent Yao <y...@apache.org>
AuthorDate: Wed Oct 11 15:49:14 2023 +0800

    [SPARK-45480][SQL][UI] Selectable Spark Plan Node on UI
    
    ### 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 #43307 from yaooqinn/SPARK-45480.
    
    Authored-by: Kent Yao <y...@apache.org>
    Signed-off-by: Kent Yao <y...@apache.org>
---
 .../sql/execution/ui/static/spark-sql-viz.css      | 18 +++++++++
 .../spark/sql/execution/ui/static/spark-sql-viz.js | 43 ++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
index dbdbf9fbf57..d6a498e9387 100644
--- 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
+++ 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.css
@@ -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;
+}
diff --git 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
index 96a7a7a3cc0..d4cc45a1639 100644
--- 
a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
+++ 
b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
@@ -47,6 +47,7 @@ function renderPlanViz() {
     .attr("ry", "5");
 
   setupLayoutForSparkPlanCluster(g, svg);
+  setupSelectionForSparkPlanNode(g);
   setupTooltipForSparkPlanNode(g);
   resizeSvg(svg);
   postprocessForAdditionalMetrics();
@@ -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);
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org
For additional commands, e-mail: commits-h...@spark.apache.org

Reply via email to