Skip to content

Commit ed25dfc

Browse files
committed
Generalize SparkUI header to display tabs dynamically
1 parent a37ad4f commit ed25dfc

15 files changed

+37
-78
lines changed

core/src/main/scala/org/apache/spark/ui/Page.scala

Lines changed: 0 additions & 22 deletions
This file was deleted.

core/src/main/scala/org/apache/spark/ui/SparkUI.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ private[spark] class SparkUI(
5555

5656
/** Initialize all components of the server. Must be called before bind(). */
5757
def start() {
58-
attachTab(new BlockManagerTab(this))
5958
attachTab(new JobProgressTab(this))
59+
attachTab(new BlockManagerTab(this))
6060
attachTab(new EnvironmentTab(this))
6161
attachTab(new ExecutorsTab(this))
6262
attachHandler(createStaticHandler(SparkUI.STATIC_RESOURCE_DIR, "/static"))

core/src/main/scala/org/apache/spark/ui/UIUtils.scala

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import scala.xml.Node
2525
/** Utility functions for generating XML pages with spark content. */
2626
private[spark] object UIUtils {
2727

28-
import Page._
29-
3028
// SimpleDateFormat is not thread-safe. Don't expose it to avoid improper use.
3129
private val dateFormat = new ThreadLocal[SimpleDateFormat]() {
3230
override def initialValue(): SimpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
@@ -62,26 +60,13 @@ private[spark] object UIUtils {
6260
basePath: String,
6361
appName: String,
6462
title: String,
65-
page: Page.Value) : Seq[Node] = {
66-
val jobs = page match {
67-
case Stages =>
68-
<li class="active"><a href={prependBaseUri(basePath, "/stages")}>Stages</a></li>
69-
case _ => <li><a href={prependBaseUri(basePath, "/stages")}>Stages</a></li>
70-
}
71-
val storage = page match {
72-
case Storage =>
73-
<li class="active"><a href={prependBaseUri(basePath, "/storage")}>Storage</a></li>
74-
case _ => <li><a href={prependBaseUri(basePath, "/storage")}>Storage</a></li>
75-
}
76-
val environment = page match {
77-
case Environment =>
78-
<li class="active"><a href={prependBaseUri(basePath, "/environment")}>Environment</a></li>
79-
case _ => <li><a href={prependBaseUri(basePath, "/environment")}>Environment</a></li>
80-
}
81-
val executors = page match {
82-
case Executors =>
83-
<li class="active"><a href={prependBaseUri(basePath, "/executors")}>Executors</a></li>
84-
case _ => <li><a href={prependBaseUri(basePath, "/executors")}>Executors</a></li>
63+
tabs: Seq[UITab],
64+
activeTab: UITab) : Seq[Node] = {
65+
66+
val header = tabs.map { tab =>
67+
<li class={if (tab == activeTab) "active" else ""}>
68+
<a href={prependBaseUri(basePath, "/" + tab.prefix)}>{tab.name}</a>
69+
</li>
8570
}
8671

8772
<html>
@@ -100,12 +85,7 @@ private[spark] object UIUtils {
10085
<a href={prependBaseUri(basePath, "/")} class="brand">
10186
<img src={prependBaseUri("/static/spark-logo-77x50px-hd.png")} />
10287
</a>
103-
<ul class="nav">
104-
{jobs}
105-
{storage}
106-
{environment}
107-
{executors}
108-
</ul>
88+
<ul class="nav">{header}</ul>
10989
<p class="navbar-text pull-right"><strong>{appName}</strong> application UI</p>
11090
</div>
11191
</div>

core/src/main/scala/org/apache/spark/ui/WebUI.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ private[spark] abstract class WebUI(securityManager: SecurityManager, basePath:
4242
protected val handlers = ArrayBuffer[ServletContextHandler]()
4343
protected var serverInfo: Option[ServerInfo] = None
4444

45+
def getTabs: Seq[UITab] = tabs.toSeq
46+
def getHandlers: Seq[ServletContextHandler] = handlers.toSeq
47+
def getListeners: Seq[SparkListener] = tabs.flatMap(_.listener)
48+
4549
/** Attach a tab to this UI, along with all of its attached pages. Only valid before bind(). */
4650
def attachTab(tab: UITab) {
4751
tab.start()
@@ -65,12 +69,6 @@ private[spark] abstract class WebUI(securityManager: SecurityManager, basePath:
6569
handlers += handler
6670
}
6771

68-
/** Return a list of listeners attached to this UI. */
69-
def getListeners = tabs.flatMap(_.listener)
70-
71-
/** Return a list of handlers attached to this UI. */
72-
def getHandlers = handlers.toSeq
73-
7472
/** Initialize all components of the server. Must be called before bind(). */
7573
def start()
7674

@@ -98,6 +96,7 @@ private[spark] abstract class WebUI(securityManager: SecurityManager, basePath:
9896
private[spark] abstract class UITab(val prefix: String) {
9997
val pages = ArrayBuffer[UIPage]()
10098
var listener: Option[SparkListener] = None
99+
var name = prefix.capitalize
101100

102101
/** Attach a page to this tab. This prepends the page's prefix with the tab's own prefix. */
103102
def attachPage(page: UIPage) {

core/src/main/scala/org/apache/spark/ui/env/EnvironmentTab.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ private[ui] class EnvironmentTab(parent: SparkUI) extends UITab("environment") {
3333
assert(listener.isDefined, "EnvironmentTab has not started yet!")
3434
listener.get.asInstanceOf[EnvironmentListener]
3535
}
36+
37+
def headerTabs: Seq[UITab] = parent.getTabs
3638
}
3739

3840
/**

core/src/main/scala/org/apache/spark/ui/env/IndexPage.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import javax.servlet.http.HttpServletRequest
2222
import scala.xml.Node
2323

2424
import org.apache.spark.ui.{UIUtils, UIPage}
25-
import org.apache.spark.ui.Page.Environment
2625

2726
private[ui] class IndexPage(parent: EnvironmentTab) extends UIPage("") {
2827
private val appName = parent.appName
@@ -46,7 +45,7 @@ private[ui] class IndexPage(parent: EnvironmentTab) extends UIPage("") {
4645
<h4>Classpath Entries</h4> {classpathEntriesTable}
4746
</span>
4847

49-
UIUtils.headerSparkPage(content, basePath, appName, "Environment", Environment)
48+
UIUtils.headerSparkPage(content, basePath, appName, "Environment", parent.headerTabs, parent)
5049
}
5150

5251
private def propertyHeader = Seq("Name", "Value")

core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ private[ui] class ExecutorsTab(parent: SparkUI) extends UITab("executors") {
3737
assert(listener.isDefined, "ExecutorsTab has not started yet!")
3838
listener.get.asInstanceOf[ExecutorsListener]
3939
}
40+
41+
def headerTabs: Seq[UITab] = parent.getTabs
4042
}
4143

4244
/**

core/src/main/scala/org/apache/spark/ui/exec/IndexPage.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import javax.servlet.http.HttpServletRequest
2222
import scala.xml.Node
2323

2424
import org.apache.spark.ui.{UIPage, UIUtils}
25-
import org.apache.spark.ui.Page.Executors
2625
import org.apache.spark.util.Utils
2726

2827
private[ui] class IndexPage(parent: ExecutorsTab) extends UIPage("") {
@@ -56,8 +55,8 @@ private[ui] class IndexPage(parent: ExecutorsTab) extends UIPage("") {
5655
</div>
5756
</div>;
5857

59-
UIUtils.headerSparkPage(
60-
content, basePath, appName, "Executors (" + execInfo.size + ")", Executors)
58+
UIUtils.headerSparkPage(content, basePath, appName, "Executors (" + execInfo.size + ")",
59+
parent.headerTabs, parent)
6160
}
6261

6362
/** Header fields for the executors table */

core/src/main/scala/org/apache/spark/ui/jobs/IndexPage.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import scala.xml.{Node, NodeSeq}
2323

2424
import org.apache.spark.scheduler.Schedulable
2525
import org.apache.spark.ui.{UIPage, UIUtils}
26-
import org.apache.spark.ui.Page.Stages
2726

2827
/** Page showing list of all ongoing and recently finished stages and pools */
2928
private[ui] class IndexPage(parent: JobProgressTab) extends UIPage("") {
@@ -92,7 +91,7 @@ private[ui] class IndexPage(parent: JobProgressTab) extends UIPage("") {
9291
<h4 id ="failed">Failed Stages ({failedStages.size})</h4> ++
9392
failedStagesTable.toNodeSeq
9493

95-
UIUtils.headerSparkPage(content, basePath, appName, "Spark Stages", Stages)
94+
UIUtils.headerSparkPage(content, basePath, appName, "Spark Stages", parent.headerTabs, parent)
9695
}
9796
}
9897
}

core/src/main/scala/org/apache/spark/ui/jobs/JobProgressTab.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ private[ui] class JobProgressTab(parent: SparkUI) extends UITab("stages") {
4242
}
4343

4444
def isFairScheduler = jobProgressListener.schedulingMode.exists(_ == SchedulingMode.FAIR)
45+
46+
def headerTabs: Seq[UITab] = parent.getTabs
4547
}

0 commit comments

Comments
 (0)