Skip to content

Commit 4790b37

Browse files
committed
[SPARK-25566]SQL UI Page support Pagination to avoid OOM
1 parent 4dc1b22 commit 4790b37

File tree

2 files changed

+56
-60
lines changed

2 files changed

+56
-60
lines changed

core/src/main/resources/org/apache/spark/ui/static/webui.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ $(function() {
8383
collapseTablePageLoad('collapse-aggregated-rdds','aggregated-rdds');
8484
collapseTablePageLoad('collapse-aggregated-activeBatches','aggregated-activeBatches');
8585
collapseTablePageLoad('collapse-aggregated-completedBatches','aggregated-completedBatches');
86-
collapseTablePageLoad('collapse-aggregated-runningExecutions','aggregated-runningExecutions');
87-
collapseTablePageLoad('collapse-aggregated-completedExecutions','aggregated-completedExecutions');
88-
collapseTablePageLoad('collapse-aggregated-failedExecutions','aggregated-failedExecutions');
86+
collapseTablePageLoad('collapse-aggregated-runningExecutions','runningExecutions');
87+
collapseTablePageLoad('collapse-aggregated-completedExecutions','completedExecutions');
88+
collapseTablePageLoad('collapse-aggregated-failedExecutions','failedExecutions');
8989
});

sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala

Lines changed: 53 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
5757

5858
if (running.nonEmpty) {
5959
val runningPageTable =
60-
jobsTable(request, "running", running, currentTime, true, true, true)
60+
executionsTable(request, "running", running, currentTime, true, true, true)
6161

6262
_content ++=
6363
<span id="running" class="collapse-aggregated-runningExecutions collapse-table"
@@ -75,7 +75,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
7575

7676
if (completed.nonEmpty) {
7777
val completedPageTable =
78-
jobsTable(request, "completed", completed, currentTime, false, true, false)
78+
executionsTable(request, "completed", completed, currentTime, false, true, false)
7979

8080
_content ++=
8181
<span id="completed" class="collapse-aggregated-completedExecutions collapse-table"
@@ -93,7 +93,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
9393

9494
if (failed.nonEmpty) {
9595
val failedPageTable =
96-
jobsTable(request, "failed", failed, currentTime, false, true, true)
96+
executionsTable(request, "failed", failed, currentTime, false, true, true)
9797

9898
_content ++=
9999
<span id="failed" class="collapse-aggregated-failedExecutions collapse-table"
@@ -149,7 +149,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
149149
UIUtils.headerSparkPage(request, "SQL", summary ++ content, parent, Some(5000))
150150
}
151151

152-
private def jobsTable(
152+
private def executionsTable(
153153
request: HttpServletRequest,
154154
executionTag: String,
155155
executionData: Seq[SQLExecutionUIData],
@@ -174,13 +174,13 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
174174
val parameterExecutionPrevPageSize = UIUtils.stripXSS(request.
175175
getParameter(executionTag + ".prevPageSize"))
176176

177-
val jobPage = Option(parameterExecutionPage).map(_.toInt).getOrElse(1)
177+
val executionPage = Option(parameterExecutionPage).map(_.toInt).getOrElse(1)
178178
val executionSortColumn = Option(parameterExecutionSortColumn).map { sortColumn =>
179179
UIUtils.decodeURLParameter(sortColumn)
180-
}.getOrElse("Id")
180+
}.getOrElse("ID")
181181
val executionSortDesc = Option(parameterExecutionSortDesc).map(_.toBoolean).getOrElse(
182-
// New executions should be shown above old jobs by default.
183-
executionSortColumn == "Id"
182+
// New executions should be shown above old executions by default.
183+
executionSortColumn == "ID"
184184
)
185185
val executionPageSize = Option(parameterExecutionPageSize).map(_.toInt).getOrElse(100)
186186
val executionPrevPageSize = Option(parameterExecutionPrevPageSize).map(_.toInt).
@@ -190,7 +190,7 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
190190
// If the user has changed to a larger page size, then go to page 1 in order to avoid
191191
// IndexOutOfBoundsException.
192192
if (executionPageSize <= executionPrevPageSize) {
193-
jobPage
193+
executionPage
194194
} else {
195195
1
196196
}
@@ -287,7 +287,7 @@ private[ui] class ExecutionPagedTable(
287287
override def headers: Seq[Node] = {
288288
// Information for each header: title, cssClass, and sortable
289289
val executionHeadersAndCssClasses: Seq[(String, String, Boolean)] =
290-
Seq(("Id", "", true), ("Description", "", true), ("Submitted", "", true),
290+
Seq(("ID", "", true), ("Description", "", true), ("Submitted", "", true),
291291
("Duration", "", true)) ++ {
292292
if (showRunningJobs && showSucceededJobs && showFailedJobs) {
293293
Seq(("Running Job IDs", "", true), ("Succeeded Job IDs", "", true),
@@ -348,46 +348,6 @@ private[ui] class ExecutionPagedTable(
348348
</thead>
349349
}
350350

351-
private def executionURL(executionID: Long): String =
352-
s"${
353-
UIUtils.prependBaseUri(
354-
request, parent.basePath)
355-
}/${
356-
parent.prefix
357-
}/execution/?id=$executionID"
358-
359-
private def jobURL(request: HttpServletRequest, jobId: Long): String =
360-
"%s/jobs/job/?id=%s".format(UIUtils.prependBaseUri(request, parent.basePath), jobId)
361-
362-
private def descriptionCell(execution: SQLExecutionUIData): Seq[Node] = {
363-
val details = if (execution.details != null && execution.details.nonEmpty) {
364-
<span onclick="this.parentNode.querySelector('.stage-details').
365-
classList.toggle('collapsed')"
366-
class="expand-details">
367-
+details
368-
</span> ++
369-
<div class="stage-details collapsed">
370-
<pre>{execution.details}</pre>
371-
</div>
372-
} else {
373-
Nil
374-
}
375-
376-
val desc = if (execution.description != null && execution.description.nonEmpty) {
377-
<a href={executionURL(execution.executionId)}>
378-
{execution.description}
379-
</a>
380-
} else {
381-
<a href={executionURL(execution.executionId)}>
382-
{execution.executionId}
383-
</a>
384-
}
385-
386-
<div>
387-
{desc}{details}
388-
</div>
389-
}
390-
391351
override def row(executionTableRow: ExecutionTableRowData): Seq[Node] = {
392352
val executionUIData = executionTableRow.executionUIData
393353
val submissionTime = executionUIData.submissionTime
@@ -420,10 +380,10 @@ private[ui] class ExecutionPagedTable(
420380
{UIUtils.formatDuration(duration)}
421381
</td>
422382
{if (showRunningJobs) {
423-
<td>
424-
{jobLinks(JobExecutionStatus.RUNNING)}
425-
</td>
426-
}}
383+
<td>
384+
{jobLinks(JobExecutionStatus.RUNNING)}
385+
</td>
386+
}}
427387
{if (showSucceededJobs) {
428388
<td>
429389
{jobLinks(JobExecutionStatus.SUCCEEDED)}
@@ -436,6 +396,42 @@ private[ui] class ExecutionPagedTable(
436396
}}
437397
</tr>
438398
}
399+
400+
private def descriptionCell(execution: SQLExecutionUIData): Seq[Node] = {
401+
val details = if (execution.details != null && execution.details.nonEmpty) {
402+
<span onclick="this.parentNode.querySelector('.stage-details').
403+
classList.toggle('collapsed')"
404+
class="expand-details">
405+
+details
406+
</span> ++
407+
<div class="stage-details collapsed">
408+
<pre>{execution.details}</pre>
409+
</div>
410+
} else {
411+
Nil
412+
}
413+
414+
val desc = if (execution.description != null && execution.description.nonEmpty) {
415+
<a href={executionURL(execution.executionId)}>
416+
{execution.description}
417+
</a>
418+
} else {
419+
<a href={executionURL(execution.executionId)}>
420+
{execution.executionId}
421+
</a>
422+
}
423+
424+
<div>
425+
{desc}{details}
426+
</div>
427+
}
428+
429+
private def jobURL(request: HttpServletRequest, jobId: Long): String =
430+
"%s/jobs/job/?id=%s".format(UIUtils.prependBaseUri(request, parent.basePath), jobId)
431+
432+
private def executionURL(executionID: Long): String =
433+
s"${UIUtils.prependBaseUri(
434+
request, parent.basePath)}/${parent.prefix}/execution/?id=$executionID"
439435
}
440436

441437

@@ -485,9 +481,9 @@ private[ui] class ExecutionDataSource(
485481
*/
486482
private def ordering(sortColumn: String, desc: Boolean): Ordering[ExecutionTableRowData] = {
487483
val ordering: Ordering[ExecutionTableRowData] = sortColumn match {
488-
case "Id" => Ordering.by(_.executionUIData.executionId)
489-
case "Description" => Ordering.by(_.executionUIData.executionId)
490-
case "Submitted" => Ordering.by(_.executionUIData.details)
484+
case "ID" => Ordering.by(_.executionUIData.executionId)
485+
case "Description" => Ordering.by(_.executionUIData.description)
486+
case "Submitted" => Ordering.by(_.executionUIData.submissionTime)
491487
case "Duration" => Ordering.by(_.duration)
492488
case "Job IDs" | "Succeeded Job IDs" => Ordering.by(_.executionUIData.jobs.flatMap {
493489
case (jobId, jobStatus) =>

0 commit comments

Comments
 (0)