diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.css b/core/src/main/resources/org/apache/spark/ui/static/webui.css index 595e80ab5e3ad106b0a442d20841e1be5fbd9e52..b157f3e0a407d4a5a5f1205fddf8d39149f9c318 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/webui.css +++ b/core/src/main/resources/org/apache/spark/ui/static/webui.css @@ -155,7 +155,7 @@ pre { display: none; } -span.expand-additional-metrics, span.expand-dag-viz { +span.expand-additional-metrics, span.expand-dag-viz, span.collapse-table { cursor: pointer; } @@ -163,7 +163,7 @@ span.additional-metric-title { cursor: pointer; } -.additional-metrics.collapsed { +.additional-metrics.collapsed, .collapsible-table.collapsed { display: none; } diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.js b/core/src/main/resources/org/apache/spark/ui/static/webui.js new file mode 100644 index 0000000000000000000000000000000000000000..e37307aa1f70597af6b0ac3908215cdb0791a383 --- /dev/null +++ b/core/src/main/resources/org/apache/spark/ui/static/webui.js @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +function collapseTablePageLoad(name, table){ + if (window.localStorage.getItem(name) == "true") { + // Set it to false so that the click function can revert it + window.localStorage.setItem(name, "false"); + collapseTable(name, table); + } +} + +function collapseTable(thisName, table){ + var status = window.localStorage.getItem(thisName) == "true"; + status = !status; + + thisClass = '.' + thisName + + // Expand the list of additional metrics. + var tableDiv = $(thisClass).parent().find('.' + table); + $(tableDiv).toggleClass('collapsed'); + + // Switch the class of the arrow from open to closed. + $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-open'); + $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-closed'); + + window.localStorage.setItem(thisName, "" + status); +} + +// Add a call to collapseTablePageLoad() on each collapsible table +// to remember if it's collapsed on each page reload +$(function() { + collapseTablePageLoad('collapse-aggregated-metrics','aggregated-metrics'); +}); \ No newline at end of file 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 4e2fe5e0e5beb20945896bd33e7e22f16fae1a97..740f5e5f7fe39796a91e256e27ffd92430005fe2 100644 --- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala +++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala @@ -169,6 +169,7 @@ private[spark] object UIUtils extends Logging { <script src={prependBaseUri("/static/additional-metrics.js")}></script> <script src={prependBaseUri("/static/timeline-view.js")}></script> <script src={prependBaseUri("/static/log-view.js")}></script> + <script src={prependBaseUri("/static/webui.js")}></script> } def vizHeaderNodes: Seq[Node] = { diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala index d986a55959b82386d980784f2de7539cdc4d2e2c..a5e2a2068949d73809068e7c8adadcd33dbd298e 100644 --- a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala +++ b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala @@ -564,6 +564,18 @@ private[ui] class StagePage(parent: StagesTab) extends WebUIPage("stage") { val maybeAccumulableTable: Seq[Node] = if (hasAccumulators) { <h4>Accumulators</h4> ++ accumulableTable } else Seq() + val aggMetrics = + <span class="collapse-aggregated-metrics collapse-table" + onClick="collapseTable('collapse-aggregated-metrics','aggregated-metrics')"> + <h4> + <span class="collapse-table-arrow arrow-open"></span> + <a>Aggregated Metrics by Executor</a> + </h4> + </span> + <div class="aggregated-metrics collapsible-table"> + {executorTable.toNodeSeq} + </div> + val content = summary ++ dagViz ++ @@ -572,9 +584,9 @@ private[ui] class StagePage(parent: StagesTab) extends WebUIPage("stage") { // Only show the tasks in the table stageData.taskData.values.toSeq.filter(t => taskIdsInPage.contains(t.taskInfo.taskId)), currentTime) ++ - <h4>Summary Metrics for {numCompleted} Completed Tasks</h4> ++ + <h4>Summary Metrics for <a href="#tasks-section">{numCompleted} Completed Tasks</a></h4> ++ <div>{summaryTable.getOrElse("No tasks have reported metrics yet.")}</div> ++ - <h4>Aggregated Metrics by Executor</h4> ++ executorTable.toNodeSeq ++ + aggMetrics ++ maybeAccumulableTable ++ <h4 id="tasks-section">Tasks</h4> ++ taskTableHTML ++ jsForScrollingDownToTaskTable UIUtils.headerSparkPage(stageHeader, content, parent, showVisualization = true)