diff --git a/core/src/main/scala/org/apache/spark/ui/PagedTable.scala b/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
index 008dcc6200d3..a002af70a919 100644
--- a/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
+++ b/core/src/main/scala/org/apache/spark/ui/PagedTable.scala
@@ -17,8 +17,9 @@
package org.apache.spark.ui
-import java.net.URLDecoder
+import java.net.{URLDecoder, URLEncoder}
import java.nio.charset.StandardCharsets.UTF_8
+import javax.servlet.http.HttpServletRequest
import scala.collection.JavaConverters._
import scala.xml.{Node, Unparsed}
@@ -297,4 +298,102 @@ private[spark] trait PagedTable[T] {
* Returns the submission path for the "go to page #" form.
*/
def goButtonFormPath: String
+
+ /**
+ * Returns parameters of other tables in the page.
+ */
+ def getParameterOtherTable(request: HttpServletRequest, tableTag: String): String = {
+ request.getParameterMap.asScala
+ .filterNot(_._1.startsWith(tableTag))
+ .map(parameter => parameter._1 + "=" + parameter._2(0))
+ .mkString("&")
+ }
+
+ /**
+ * Returns parameter of this table.
+ */
+ def getTableParameters(
+ request: HttpServletRequest,
+ tableTag: String,
+ defaultSortColumn: String): (String, Boolean, Int) = {
+ val parameterSortColumn = request.getParameter(s"$tableTag.sort")
+ val parameterSortDesc = request.getParameter(s"$tableTag.desc")
+ val parameterPageSize = request.getParameter(s"$tableTag.pageSize")
+ val sortColumn = Option(parameterSortColumn).map { sortColumn =>
+ UIUtils.decodeURLParameter(sortColumn)
+ }.getOrElse(defaultSortColumn)
+ val desc = Option(parameterSortDesc).map(_.toBoolean).getOrElse(
+ sortColumn == defaultSortColumn
+ )
+ val pageSize = Option(parameterPageSize).map(_.toInt).getOrElse(100)
+
+ (sortColumn, desc, pageSize)
+ }
+
+ /**
+ * Check if given sort column is valid or not. If invalid then an exception is thrown.
+ */
+ def isSortColumnValid(
+ headerInfo: Seq[(String, Boolean, Option[String])],
+ sortColumn: String): Unit = {
+ if (!headerInfo.filter(_._2).map(_._1).contains(sortColumn)) {
+ throw new IllegalArgumentException(s"Unknown column: $sortColumn")
+ }
+ }
+
+ def headerRow(
+ headerInfo: Seq[(String, Boolean, Option[String])],
+ desc: Boolean,
+ pageSize: Int,
+ sortColumn: String,
+ parameterPath: String,
+ tableTag: String,
+ headerId: String): Seq[Node] = {
+ val row: Seq[Node] = {
+ headerInfo.map { case (header, sortable, tooltip) =>
+ if (header == sortColumn) {
+ val headerLink = Unparsed(
+ parameterPath +
+ s"&$tableTag.sort=${URLEncoder.encode(header, UTF_8.name())}" +
+ s"&$tableTag.desc=${!desc}" +
+ s"&$tableTag.pageSize=$pageSize" +
+ s"#$headerId")
+ val arrow = if (desc) "▾" else "▴" // UP or DOWN
+
+
@@ -146,26 +122,8 @@ private[ui] class ThriftServerPage(parent: ThriftServerTab) extends WebUIPage(""
val sessionTableTag = "sessionstat"
- val parameterOtherTable = request.getParameterMap().asScala
- .filterNot(_._1.startsWith(sessionTableTag))
- .map { case (name, vals) =>
- name + "=" + vals(0)
- }
-
- val parameterSessionTablePage = request.getParameter(s"$sessionTableTag.page")
- val parameterSessionTableSortColumn = request.getParameter(s"$sessionTableTag.sort")
- val parameterSessionTableSortDesc = request.getParameter(s"$sessionTableTag.desc")
- val parameterSessionPageSize = request.getParameter(s"$sessionTableTag.pageSize")
-
- val sessionTablePage = Option(parameterSessionTablePage).map(_.toInt).getOrElse(1)
- val sessionTableSortColumn = Option(parameterSessionTableSortColumn).map { sortColumn =>
- UIUtils.decodeURLParameter(sortColumn)
- }.getOrElse("Start Time")
- val sessionTableSortDesc = Option(parameterSessionTableSortDesc).map(_.toBoolean).getOrElse(
- // New session should be shown above old session by default.
- (sessionTableSortColumn == "Start Time")
- )
- val sessionTablePageSize = Option(parameterSessionPageSize).map(_.toInt).getOrElse(100)
+ val sessionTablePage =
+ Option(request.getParameter(s"$sessionTableTag.page")).map(_.toInt).getOrElse(1)
try {
Some(new SessionStatsPagedTable(
@@ -174,11 +132,7 @@ private[ui] class ThriftServerPage(parent: ThriftServerTab) extends WebUIPage(""
store.getSessionList,
"sqlserver",
UIUtils.prependBaseUri(request, parent.basePath),
- parameterOtherTable,
- sessionTableTag,
- pageSize = sessionTablePageSize,
- sortColumn = sessionTableSortColumn,
- desc = sessionTableSortDesc
+ sessionTableTag
).table(sessionTablePage))
} catch {
case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>
@@ -216,15 +170,15 @@ private[ui] class SqlStatsPagedTable(
data: Seq[ExecutionInfo],
subPath: String,
basePath: String,
- parameterOtherTable: Iterable[String],
- sqlStatsTableTag: String,
- pageSize: Int,
- sortColumn: String,
- desc: Boolean) extends PagedTable[SqlStatsTableRow] {
+ sqlStatsTableTag: String) extends PagedTable[SqlStatsTableRow] {
+
+ private val (sortColumn, desc, pageSize) =
+ getTableParameters(request, sqlStatsTableTag, "Start Time")
override val dataSource = new SqlStatsTableDataSource(data, pageSize, sortColumn, desc)
- private val parameterPath = s"$basePath/$subPath/?${parameterOtherTable.mkString("&")}"
+ private val parameterPath =
+ s"$basePath/$subPath/?${getParameterOtherTable(request, sqlStatsTableTag)}"
override def tableId: String = sqlStatsTableTag
@@ -238,7 +192,8 @@ private[ui] class SqlStatsPagedTable(
s"&$pageNumberFormField=$page" +
s"&$sqlStatsTableTag.sort=$encodedSortColumn" +
s"&$sqlStatsTableTag.desc=$desc" +
- s"&$pageSizeFormField=$pageSize"
+ s"&$pageSizeFormField=$pageSize" +
+ s"#$sqlStatsTableTag"
}
override def pageSizeFormField: String = s"$sqlStatsTableTag.pageSize"
@@ -247,73 +202,29 @@ private[ui] class SqlStatsPagedTable(
override def goButtonFormPath: String = {
val encodedSortColumn = URLEncoder.encode(sortColumn, UTF_8.name())
- s"$parameterPath&$sqlStatsTableTag.sort=$encodedSortColumn&$sqlStatsTableTag.desc=$desc"
+ s"$parameterPath&$sqlStatsTableTag.sort=$encodedSortColumn" +
+ s"&$sqlStatsTableTag.desc=$desc#$sqlStatsTableTag"
}
override def headers: Seq[Node] = {
- val sqlTableHeaders = Seq("User", "JobID", "GroupID", "Start Time", "Finish Time",
- "Close Time", "Execution Time", "Duration", "Statement", "State", "Detail")
-
- val tooltips = Seq(None, None, None, None, Some(THRIFT_SERVER_FINISH_TIME),
- Some(THRIFT_SERVER_CLOSE_TIME), Some(THRIFT_SERVER_EXECUTION),
- Some(THRIFT_SERVER_DURATION), None, None, None)
-
- assert(sqlTableHeaders.length == tooltips.length)
-
- val headerRow: Seq[Node] = {
- sqlTableHeaders.zip(tooltips).map { case (header, tooltip) =>
- if (header == sortColumn) {
- val headerLink = Unparsed(
- parameterPath +
- s"&$sqlStatsTableTag.sort=${URLEncoder.encode(header, UTF_8.name())}" +
- s"&$sqlStatsTableTag.desc=${!desc}" +
- s"&$sqlStatsTableTag.pageSize=$pageSize" +
- s"#$sqlStatsTableTag")
- val arrow = if (desc) "▾" else "▴" // UP or DOWN
-
- if (tooltip.nonEmpty) {
-
-
-
- {header} {Unparsed(arrow)}
-
-
- |
- } else {
-
-
- {header} {Unparsed(arrow)}
-
- |
- }
- } else {
- val headerLink = Unparsed(
- parameterPath +
- s"&$sqlStatsTableTag.sort=${URLEncoder.encode(header, UTF_8.name())}" +
- s"&$sqlStatsTableTag.pageSize=$pageSize" +
- s"#$sqlStatsTableTag")
-
- if(tooltip.nonEmpty) {
-
-
-
- {header}
-
-
- |
- } else {
-
-
- {header}
-
- |
- }
- }
- }
- }
-
- {headerRow}
-
+ val sqlTableHeadersAndTooltips: Seq[(String, Boolean, Option[String])] =
+ Seq(
+ ("User", true, None),
+ ("JobID", true, None),
+ ("GroupID", true, None),
+ ("Start Time", true, None),
+ ("Finish Time", true, Some(THRIFT_SERVER_FINISH_TIME)),
+ ("Close Time", true, Some(THRIFT_SERVER_CLOSE_TIME)),
+ ("Execution Time", true, Some(THRIFT_SERVER_EXECUTION)),
+ ("Duration", true, Some(THRIFT_SERVER_DURATION)),
+ ("Statement", true, None),
+ ("State", true, None),
+ ("Detail", true, None))
+
+ isSortColumnValid(sqlTableHeadersAndTooltips, sortColumn)
+
+ headerRow(sqlTableHeadersAndTooltips, desc, pageSize, sortColumn, parameterPath,
+ sqlStatsTableTag, sqlStatsTableTag)
}
override def row(sqlStatsTableRow: SqlStatsTableRow): Seq[Node] = {
@@ -391,15 +302,15 @@ private[ui] class SessionStatsPagedTable(
data: Seq[SessionInfo],
subPath: String,
basePath: String,
- parameterOtherTable: Iterable[String],
- sessionStatsTableTag: String,
- pageSize: Int,
- sortColumn: String,
- desc: Boolean) extends PagedTable[SessionInfo] {
+ sessionStatsTableTag: String) extends PagedTable[SessionInfo] {
+
+ private val (sortColumn, desc, pageSize) =
+ getTableParameters(request, sessionStatsTableTag, "Start Time")
override val dataSource = new SessionStatsTableDataSource(data, pageSize, sortColumn, desc)
- private val parameterPath = s"$basePath/$subPath/?${parameterOtherTable.mkString("&")}"
+ private val parameterPath =
+ s"$basePath/$subPath/?${getParameterOtherTable(request, sessionStatsTableTag)}"
override def tableId: String = sessionStatsTableTag
@@ -413,7 +324,8 @@ private[ui] class SessionStatsPagedTable(
s"&$pageNumberFormField=$page" +
s"&$sessionStatsTableTag.sort=$encodedSortColumn" +
s"&$sessionStatsTableTag.desc=$desc" +
- s"&$pageSizeFormField=$pageSize"
+ s"&$pageSizeFormField=$pageSize" +
+ s"#$sessionStatsTableTag"
}
override def pageSizeFormField: String = s"$sessionStatsTableTag.pageSize"
@@ -422,70 +334,25 @@ private[ui] class SessionStatsPagedTable(
override def goButtonFormPath: String = {
val encodedSortColumn = URLEncoder.encode(sortColumn, UTF_8.name())
- s"$parameterPath&$sessionStatsTableTag.sort=$encodedSortColumn&$sessionStatsTableTag.desc=$desc"
+ s"$parameterPath&$sessionStatsTableTag.sort=$encodedSortColumn" +
+ s"&$sessionStatsTableTag.desc=$desc#$sessionStatsTableTag"
}
override def headers: Seq[Node] = {
- val sessionTableHeaders =
- Seq("User", "IP", "Session ID", "Start Time", "Finish Time", "Duration", "Total Execute")
-
- val tooltips = Seq(None, None, None, None, None, Some(THRIFT_SESSION_DURATION),
- Some(THRIFT_SESSION_TOTAL_EXECUTE))
- assert(sessionTableHeaders.length == tooltips.length)
- val colWidthAttr = s"${100.toDouble / sessionTableHeaders.size}%"
-
- val headerRow: Seq[Node] = {
- sessionTableHeaders.zip(tooltips).map { case (header, tooltip) =>
- if (header == sortColumn) {
- val headerLink = Unparsed(
- parameterPath +
- s"&$sessionStatsTableTag.sort=${URLEncoder.encode(header, UTF_8.name())}" +
- s"&$sessionStatsTableTag.desc=${!desc}" +
- s"&$sessionStatsTableTag.pageSize=$pageSize" +
- s"#$sessionStatsTableTag")
- val arrow = if (desc) "▾" else "▴" // UP or DOWN
-
-
- {
- if (tooltip.nonEmpty) {
-
- {header} {Unparsed(arrow)}
-
- } else {
-
- {header} {Unparsed(arrow)}
-
- }
- }
-
- |
-
- } else {
- val headerLink = Unparsed(
- parameterPath +
- s"&$sessionStatsTableTag.sort=${URLEncoder.encode(header, UTF_8.name())}" +
- s"&$sessionStatsTableTag.pageSize=$pageSize" +
- s"#$sessionStatsTableTag")
-
-
-
- {
- if (tooltip.nonEmpty) {
-
- {header}
-
- } else {
- {header}
- }
- }
-
- |
- }
- }
- }
-
- {headerRow}
-
+ val sessionTableHeadersAndTooltips: Seq[(String, Boolean, Option[String])] =
+ Seq(
+ ("User", true, None),
+ ("IP", true, None),
+ ("Session ID", true, None),
+ ("Start Time", true, None),
+ ("Finish Time", true, None),
+ ("Duration", true, Some(THRIFT_SESSION_DURATION)),
+ ("Total Execute", true, Some(THRIFT_SESSION_TOTAL_EXECUTE)))
+
+ isSortColumnValid(sessionTableHeadersAndTooltips, sortColumn)
+
+ headerRow(sessionTableHeadersAndTooltips, desc, pageSize, sortColumn,
+ parameterPath, sessionStatsTableTag, sessionStatsTableTag)
}
override def row(session: SessionInfo): Seq[Node] = {
diff --git a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
index 2d7adf552738..87165cc8cac4 100644
--- a/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
+++ b/sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala
@@ -19,7 +19,6 @@ package org.apache.spark.sql.hive.thriftserver.ui
import javax.servlet.http.HttpServletRequest
-import scala.collection.JavaConverters._
import scala.xml.Node
import org.apache.spark.internal.Logging
@@ -77,26 +76,8 @@ private[ui] class ThriftServerSessionPage(parent: ThriftServerTab)
val sqlTableTag = "sqlsessionstat"
- val parameterOtherTable = request.getParameterMap().asScala
- .filterNot(_._1.startsWith(sqlTableTag))
- .map { case (name, vals) =>
- name + "=" + vals(0)
- }
-
- val parameterSqlTablePage = request.getParameter(s"$sqlTableTag.page")
- val parameterSqlTableSortColumn = request.getParameter(s"$sqlTableTag.sort")
- val parameterSqlTableSortDesc = request.getParameter(s"$sqlTableTag.desc")
- val parameterSqlPageSize = request.getParameter(s"$sqlTableTag.pageSize")
-
- val sqlTablePage = Option(parameterSqlTablePage).map(_.toInt).getOrElse(1)
- val sqlTableSortColumn = Option(parameterSqlTableSortColumn).map { sortColumn =>
- UIUtils.decodeURLParameter(sortColumn)
- }.getOrElse("Start Time")
- val sqlTableSortDesc = Option(parameterSqlTableSortDesc).map(_.toBoolean).getOrElse(
- // New executions should be shown above old executions by default.
- sqlTableSortColumn == "Start Time"
- )
- val sqlTablePageSize = Option(parameterSqlPageSize).map(_.toInt).getOrElse(100)
+ val sqlTablePage =
+ Option(request.getParameter(s"$sqlTableTag.page")).map(_.toInt).getOrElse(1)
try {
Some(new SqlStatsPagedTable(
@@ -105,11 +86,7 @@ private[ui] class ThriftServerSessionPage(parent: ThriftServerTab)
executionList,
"sqlserver/session",
UIUtils.prependBaseUri(request, parent.basePath),
- parameterOtherTable,
- sqlTableTag,
- pageSize = sqlTablePageSize,
- sortColumn = sqlTableSortColumn,
- desc = sqlTableSortDesc
+ sqlTableTag
).table(sqlTablePage))
} catch {
case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException) =>