Skip to content

Commit 478b71d

Browse files
nblintaozsxwing
authored andcommitted
[SPARK-15591][WEBUI] Paginate Stage Table in Stages tab
## What changes were proposed in this pull request? This patch adds pagination support for the Stage Tables in the Stage tab. Pagination is provided for all of the four Job Tables (active, pending, completed, and failed). Besides, the paged stage tables are also used in JobPage (the detail page for one job) and PoolPage. Interactions (jumping, sorting, and setting page size) for paged tables are also included. ## How was this patch tested? Tested manually by using checking the Web UI after completing and failing hundreds of jobs. Same as the testings for [Paginate Job Table in Jobs tab](apache#13620). This shows the pagination for completed stages: ![paged stage table](https://cloud.githubusercontent.com/assets/5558370/16125696/5804e35e-3427-11e6-8923-5c5948982648.png) Author: Tao Lin <[email protected]> Closes apache#13708 from nblintao/stageTable.
1 parent 21eadd1 commit 478b71d

File tree

5 files changed

+441
-141
lines changed

5 files changed

+441
-141
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ private[ui] trait PagedTable[T] {
179179
Splitter
180180
.on('&')
181181
.trimResults()
182+
.omitEmptyStrings()
182183
.withKeyValueSeparator("=")
183184
.split(querystring)
184185
.asScala

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,24 @@ private[ui] class AllStagesPage(parent: StagesTab) extends WebUIPage("") {
3838
val numCompletedStages = listener.numCompletedStages
3939
val failedStages = listener.failedStages.reverse.toSeq
4040
val numFailedStages = listener.numFailedStages
41-
val now = System.currentTimeMillis
41+
val subPath = "stages"
4242

4343
val activeStagesTable =
44-
new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
45-
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
46-
killEnabled = parent.killEnabled)
44+
new StageTableBase(request, activeStages, "activeStage", parent.basePath, subPath,
45+
parent.progressListener, parent.isFairScheduler,
46+
killEnabled = parent.killEnabled, isFailedStage = false)
4747
val pendingStagesTable =
48-
new StageTableBase(pendingStages.sortBy(_.submissionTime).reverse,
49-
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
50-
killEnabled = false)
48+
new StageTableBase(request, pendingStages, "pendingStage", parent.basePath, subPath,
49+
parent.progressListener, parent.isFairScheduler,
50+
killEnabled = false, isFailedStage = false)
5151
val completedStagesTable =
52-
new StageTableBase(completedStages.sortBy(_.submissionTime).reverse, parent.basePath,
53-
parent.progressListener, isFairScheduler = parent.isFairScheduler, killEnabled = false)
52+
new StageTableBase(request, completedStages, "completedStage", parent.basePath, subPath,
53+
parent.progressListener, parent.isFairScheduler,
54+
killEnabled = false, isFailedStage = false)
5455
val failedStagesTable =
55-
new FailedStageTable(failedStages.sortBy(_.submissionTime).reverse, parent.basePath,
56-
parent.progressListener, isFairScheduler = parent.isFairScheduler)
56+
new StageTableBase(request, failedStages, "failedStage", parent.basePath, subPath,
57+
parent.progressListener, parent.isFairScheduler,
58+
killEnabled = false, isFailedStage = true)
5759

5860
// For now, pool information is only accessible in live UIs
5961
val pools = sc.map(_.getAllPools).getOrElse(Seq.empty[Schedulable])
@@ -136,3 +138,4 @@ private[ui] class AllStagesPage(parent: StagesTab) extends WebUIPage("") {
136138
}
137139
}
138140
}
141+

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,20 +229,24 @@ private[ui] class JobPage(parent: JobsTab) extends WebUIPage("job") {
229229
}
230230
}
231231

232+
val basePath = "jobs/job"
233+
232234
val activeStagesTable =
233-
new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
234-
parent.basePath, parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler,
235-
killEnabled = parent.killEnabled)
235+
new StageTableBase(request, activeStages, "activeStage", parent.basePath,
236+
basePath, parent.jobProgresslistener, parent.isFairScheduler,
237+
killEnabled = parent.killEnabled, isFailedStage = false)
236238
val pendingOrSkippedStagesTable =
237-
new StageTableBase(pendingOrSkippedStages.sortBy(_.stageId).reverse,
238-
parent.basePath, parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler,
239-
killEnabled = false)
239+
new StageTableBase(request, pendingOrSkippedStages, "pendingStage", parent.basePath,
240+
basePath, parent.jobProgresslistener, parent.isFairScheduler,
241+
killEnabled = false, isFailedStage = false)
240242
val completedStagesTable =
241-
new StageTableBase(completedStages.sortBy(_.submissionTime).reverse, parent.basePath,
242-
parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler, killEnabled = false)
243+
new StageTableBase(request, completedStages, "completedStage", parent.basePath,
244+
basePath, parent.jobProgresslistener, parent.isFairScheduler,
245+
killEnabled = false, isFailedStage = false)
243246
val failedStagesTable =
244-
new FailedStageTable(failedStages.sortBy(_.submissionTime).reverse, parent.basePath,
245-
parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler)
247+
new StageTableBase(request, failedStages, "failedStage", parent.basePath,
248+
basePath, parent.jobProgresslistener, parent.isFairScheduler,
249+
killEnabled = false, isFailedStage = true)
246250

247251
val shouldShowActiveStages = activeStages.nonEmpty
248252
val shouldShowPendingStages = !isComplete && pendingOrSkippedStages.nonEmpty

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,22 @@ private[ui] class PoolPage(parent: StagesTab) extends WebUIPage("pool") {
4242
case Some(s) => s.values.toSeq
4343
case None => Seq[StageInfo]()
4444
}
45-
val activeStagesTable = new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
46-
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
47-
killEnabled = parent.killEnabled)
45+
val shouldShowActiveStages = activeStages.nonEmpty
46+
val activeStagesTable =
47+
new StageTableBase(request, activeStages, "activeStage", parent.basePath, "stages/pool",
48+
parent.progressListener, parent.isFairScheduler, parent.killEnabled,
49+
isFailedStage = false)
4850

4951
// For now, pool information is only accessible in live UIs
5052
val pools = sc.map(_.getPoolForName(poolName).getOrElse {
5153
throw new IllegalArgumentException(s"Unknown poolname: $poolName")
5254
}).toSeq
5355
val poolTable = new PoolTable(pools, parent)
5456

55-
val content =
56-
<h4>Summary </h4> ++ poolTable.toNodeSeq ++
57-
<h4>{activeStages.size} Active Stages</h4> ++ activeStagesTable.toNodeSeq
57+
var content = <h4>Summary </h4> ++ poolTable.toNodeSeq
58+
if (shouldShowActiveStages) {
59+
content ++= <h4>{activeStages.size} Active Stages</h4> ++ activeStagesTable.toNodeSeq
60+
}
5861

5962
UIUtils.headerSparkPage("Fair Scheduler Pool: " + poolName, content, parent)
6063
}

0 commit comments

Comments
 (0)