Skip to content

Commit 8aac163

Browse files
committed
Add basic application table
1 parent c086bd5 commit 8aac163

File tree

2 files changed

+38
-41
lines changed

2 files changed

+38
-41
lines changed

core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ import org.apache.spark.scheduler.ReplayListenerBus
4444
* @param baseLogDir The base directory in which event logs are found
4545
* @param requestedPort The requested port to which this server is to be bound
4646
*/
47-
class HistoryServer(baseLogDir: String, requestedPort: Int, conf: SparkConf)
47+
class HistoryServer(val baseLogDir: String, requestedPort: Int, conf: SparkConf)
4848
extends SparkUIContainer("History Server") with Logging {
4949

50-
private val host = Utils.localHostName()
50+
private val host = Option(System.getenv("SPARK_PUBLIC_DNS")).getOrElse(Utils.localHostName())
5151
private val port = requestedPort
5252
private val indexPage = new IndexPage(this)
5353
private val fileSystem = Utils.getHadoopFileSystem(new URI(baseLogDir))
@@ -101,36 +101,37 @@ class HistoryServer(baseLogDir: String, requestedPort: Int, conf: SparkConf)
101101

102102
// Remove any outdated SparkUIs
103103
val logPaths = logDirs.map(_.getPath.toString)
104-
logPathToUI.keys.foreach { path =>
104+
logPathToUI.foreach { case (path, ui) =>
105105
if (!logPaths.contains(path)) {
106+
detachUI(ui)
106107
logPathToUI.remove(path)
107108
logPathToLastUpdated.remove(path)
108109
}
109110
}
110-
111-
logWarning("By the end of check for logs, the map looks like")
112-
logPathToUI.foreach { case (k, v) => logWarning("* %s".format(k)) }
113111
}
114112

115113
/** Attempt to render a new SparkUI from event logs residing in the given log directory. */
116114
def maybeRenderUI(logPath: String, lastUpdated: Long) {
117-
logWarning("Maybe rendering UI %s".format(logPath))
118-
119-
val appName = logPath.split("/").last
115+
val appName = getAppName(logPath)
120116
val replayBus = new ReplayListenerBus(conf)
121117
val ui = new SparkUI(conf, replayBus, appName, "/history/%s".format(appName))
122118

123119
// Do not call ui.bind() to avoid creating a new server for each application
124120
ui.start()
125121
val success = replayBus.replay(logPath)
126-
logWarning("Just replayed the events. Successful? %s".format(success))
127122
if (success) {
128123
attachUI(ui)
129124
logPathToUI(logPath) = ui
130125
logPathToLastUpdated(logPath) = lastUpdated
131126
}
132127
}
133128

129+
/** Parse app name from the given log path. */
130+
def getAppName(logPath: String): String = logPath.split("/").last
131+
132+
/** Return the address of this server. */
133+
def getAddress = "http://" + host + ":" + boundPort
134+
134135
}
135136

136137
object HistoryServer {

core/src/main/scala/org/apache/spark/deploy/history/IndexPage.scala

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,55 +17,51 @@
1717

1818
package org.apache.spark.deploy.history
1919

20+
import java.text.SimpleDateFormat
21+
import java.util.Date
2022
import javax.servlet.http.HttpServletRequest
2123

2224
import scala.xml.Node
2325

24-
import org.apache.spark.deploy.DeployWebUI
25-
import org.apache.spark.deploy.master.ApplicationInfo
26-
import org.apache.spark.ui.UIUtils
27-
import org.apache.spark.util.Utils
26+
import org.apache.spark.ui.{SparkUI, UIUtils}
2827

2928
private[spark] class IndexPage(parent: HistoryServer) {
29+
val dateFmt = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
3030

3131
def render(request: HttpServletRequest): Seq[Node] = {
32+
// Check if logs have been updated
33+
parent.checkForLogs()
34+
35+
// Populate app table, with most recently modified first
36+
val appRows = parent.logPathToLastUpdated.toSeq
37+
.sortBy { case (path, lastUpdated) => -lastUpdated }
38+
.map { case (path, lastUpdated) =>
39+
// (appName, lastUpdated, UI)
40+
(parent.getAppName(path), lastUpdated, parent.logPathToUI(path))
41+
}
42+
val appTable = UIUtils.listingTable(appHeader, appRow, appRows)
43+
3244
val content =
3345
<div class="row-fluid">
3446
<div class="span12">
3547
<ul class="unstyled">
36-
<li>
37-
<strong>Welcome to the Fastest and Furious-est HistoryServer in the World!</strong>
38-
</li>
39-
{
40-
parent.logPathToUI.map { case (path, ui) =>
41-
<li>{path} at {ui.basePath}</li>
42-
}
43-
}
48+
<li><strong>Event Log Location: </strong> {parent.baseLogDir}</li>
49+
<h4>Applications</h4> {appTable}
4450
</ul>
4551
</div>
4652
</div>
4753

4854
UIUtils.basicSparkPage(content, "History Server")
4955
}
5056

51-
def appRow(app: ApplicationInfo): Seq[Node] = {
52-
<tr>
53-
<td>
54-
<a href={"app?appId=" + app.id}>{app.id}</a>
55-
</td>
56-
<td>
57-
<a href={app.desc.appUiUrl}>{app.desc.name}</a>
58-
</td>
59-
<td>
60-
{app.coresGranted}
61-
</td>
62-
<td sorttable_customkey={app.desc.memoryPerSlave.toString}>
63-
{Utils.megabytesToString(app.desc.memoryPerSlave)}
64-
</td>
65-
<td>{DeployWebUI.formatDate(app.submitDate)}</td>
66-
<td>{app.desc.user}</td>
67-
<td>{app.state.toString}</td>
68-
<td>{DeployWebUI.formatDuration(app.duration)}</td>
69-
</tr>
57+
private val appHeader = Seq[String]("App Name", "Last Updated")
58+
59+
private def appRow(info: (String, Long, SparkUI)): Seq[Node] = {
60+
info match { case (appName, lastUpdated, ui) =>
61+
<tr>
62+
<td><a href={parent.getAddress + ui.basePath}>{appName}</a></td>
63+
<td>{dateFmt.format(new Date(lastUpdated))}</td>
64+
</tr>
65+
}
7066
}
7167
}

0 commit comments

Comments
 (0)