Skip to content

Commit

Permalink
[SPARK-15591][WEBUI] Paginate Stage Table in Stages tab
Browse files Browse the repository at this point in the history
## 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](#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 <nblintao@gmail.com>

Closes #13708 from nblintao/stageTable.
  • Loading branch information
nblintao authored and zsxwing committed Jul 6, 2016
1 parent 21eadd1 commit 478b71d
Show file tree
Hide file tree
Showing 5 changed files with 441 additions and 141 deletions.
1 change: 1 addition & 0 deletions core/src/main/scala/org/apache/spark/ui/PagedTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ private[ui] trait PagedTable[T] {
Splitter
.on('&')
.trimResults()
.omitEmptyStrings()
.withKeyValueSeparator("=")
.split(querystring)
.asScala
Expand Down
25 changes: 14 additions & 11 deletions core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,24 @@ private[ui] class AllStagesPage(parent: StagesTab) extends WebUIPage("") {
val numCompletedStages = listener.numCompletedStages
val failedStages = listener.failedStages.reverse.toSeq
val numFailedStages = listener.numFailedStages
val now = System.currentTimeMillis
val subPath = "stages"

val activeStagesTable =
new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
killEnabled = parent.killEnabled)
new StageTableBase(request, activeStages, "activeStage", parent.basePath, subPath,
parent.progressListener, parent.isFairScheduler,
killEnabled = parent.killEnabled, isFailedStage = false)
val pendingStagesTable =
new StageTableBase(pendingStages.sortBy(_.submissionTime).reverse,
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
killEnabled = false)
new StageTableBase(request, pendingStages, "pendingStage", parent.basePath, subPath,
parent.progressListener, parent.isFairScheduler,
killEnabled = false, isFailedStage = false)
val completedStagesTable =
new StageTableBase(completedStages.sortBy(_.submissionTime).reverse, parent.basePath,
parent.progressListener, isFairScheduler = parent.isFairScheduler, killEnabled = false)
new StageTableBase(request, completedStages, "completedStage", parent.basePath, subPath,
parent.progressListener, parent.isFairScheduler,
killEnabled = false, isFailedStage = false)
val failedStagesTable =
new FailedStageTable(failedStages.sortBy(_.submissionTime).reverse, parent.basePath,
parent.progressListener, isFairScheduler = parent.isFairScheduler)
new StageTableBase(request, failedStages, "failedStage", parent.basePath, subPath,
parent.progressListener, parent.isFairScheduler,
killEnabled = false, isFailedStage = true)

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

24 changes: 14 additions & 10 deletions core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,24 @@ private[ui] class JobPage(parent: JobsTab) extends WebUIPage("job") {
}
}

val basePath = "jobs/job"

val activeStagesTable =
new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
parent.basePath, parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler,
killEnabled = parent.killEnabled)
new StageTableBase(request, activeStages, "activeStage", parent.basePath,
basePath, parent.jobProgresslistener, parent.isFairScheduler,
killEnabled = parent.killEnabled, isFailedStage = false)
val pendingOrSkippedStagesTable =
new StageTableBase(pendingOrSkippedStages.sortBy(_.stageId).reverse,
parent.basePath, parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler,
killEnabled = false)
new StageTableBase(request, pendingOrSkippedStages, "pendingStage", parent.basePath,
basePath, parent.jobProgresslistener, parent.isFairScheduler,
killEnabled = false, isFailedStage = false)
val completedStagesTable =
new StageTableBase(completedStages.sortBy(_.submissionTime).reverse, parent.basePath,
parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler, killEnabled = false)
new StageTableBase(request, completedStages, "completedStage", parent.basePath,
basePath, parent.jobProgresslistener, parent.isFairScheduler,
killEnabled = false, isFailedStage = false)
val failedStagesTable =
new FailedStageTable(failedStages.sortBy(_.submissionTime).reverse, parent.basePath,
parent.jobProgresslistener, isFairScheduler = parent.isFairScheduler)
new StageTableBase(request, failedStages, "failedStage", parent.basePath,
basePath, parent.jobProgresslistener, parent.isFairScheduler,
killEnabled = false, isFailedStage = true)

val shouldShowActiveStages = activeStages.nonEmpty
val shouldShowPendingStages = !isComplete && pendingOrSkippedStages.nonEmpty
Expand Down
15 changes: 9 additions & 6 deletions core/src/main/scala/org/apache/spark/ui/jobs/PoolPage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,22 @@ private[ui] class PoolPage(parent: StagesTab) extends WebUIPage("pool") {
case Some(s) => s.values.toSeq
case None => Seq[StageInfo]()
}
val activeStagesTable = new StageTableBase(activeStages.sortBy(_.submissionTime).reverse,
parent.basePath, parent.progressListener, isFairScheduler = parent.isFairScheduler,
killEnabled = parent.killEnabled)
val shouldShowActiveStages = activeStages.nonEmpty
val activeStagesTable =
new StageTableBase(request, activeStages, "activeStage", parent.basePath, "stages/pool",
parent.progressListener, parent.isFairScheduler, parent.killEnabled,
isFailedStage = false)

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

val content =
<h4>Summary </h4> ++ poolTable.toNodeSeq ++
<h4>{activeStages.size} Active Stages</h4> ++ activeStagesTable.toNodeSeq
var content = <h4>Summary </h4> ++ poolTable.toNodeSeq
if (shouldShowActiveStages) {
content ++= <h4>{activeStages.size} Active Stages</h4> ++ activeStagesTable.toNodeSeq
}

UIUtils.headerSparkPage("Fair Scheduler Pool: " + poolName, content, parent)
}
Expand Down
Loading

0 comments on commit 478b71d

Please sign in to comment.