aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPatrick Wendell <pwendell@gmail.com>2013-06-18 09:50:24 -0700
committerPatrick Wendell <pwendell@gmail.com>2013-06-22 10:31:36 -0700
commit9161db5478c3e8c1c124070bacdf571b744cee22 (patch)
tree696c9f86b205dcc6e2ee89661cee79c747f774a1 /core
parente55cf0245fa7d352f948312bb81cf2c09fe63d6f (diff)
downloadspark-9161db5478c3e8c1c124070bacdf571b744cee22.tar.gz
spark-9161db5478c3e8c1c124070bacdf571b744cee22.tar.bz2
spark-9161db5478c3e8c1c124070bacdf571b744cee22.zip
Cleaning up master web UI
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/spark/deploy/master/MasterWebUI.scala201
1 files changed, 93 insertions, 108 deletions
diff --git a/core/src/main/scala/spark/deploy/master/MasterWebUI.scala b/core/src/main/scala/spark/deploy/master/MasterWebUI.scala
index c76b5b1e0e..0b7d163980 100644
--- a/core/src/main/scala/spark/deploy/master/MasterWebUI.scala
+++ b/core/src/main/scala/spark/deploy/master/MasterWebUI.scala
@@ -1,27 +1,19 @@
package spark.deploy.master
-import akka.actor.{ActorRef, ActorSystem}
+import akka.actor.{ActorRef}
import akka.dispatch.Await
import akka.pattern.ask
-import akka.util.{Duration, Timeout}
+import akka.util.{Duration}
import akka.util.duration._
-import cc.spray.Directives
-import cc.spray.directives._
-import cc.spray.typeconversion.TwirlSupport._
-import cc.spray.http.MediaTypes
-import cc.spray.typeconversion.SprayJsonSupport._
import scala.xml.Node
import spark.{Logging, Utils}
import spark.util.{WebUI => UtilsWebUI}
import spark.deploy._
-import spark.deploy.JsonProtocol._
-import concurrent.Future
import org.eclipse.jetty.server.Handler
import spark.util.WebUI._
import spark.deploy.MasterState
import javax.servlet.http.HttpServletRequest
-import java.util.concurrent.TimeUnit
/**
* Web UI server for the standalone master.
@@ -47,9 +39,11 @@ class MasterWebUI(master: ActorRef) extends Logging {
val handlers = Array[(String, Handler)](
("/static", createStaticHandler(MasterWebUI.STATIC_RESOURCE_DIR)),
+ ("/app", (request: HttpServletRequest) => appDetail(request)),
("*", (request: HttpServletRequest) => index)
)
+ /** Executor details for a particular application */
def appDetail(request: HttpServletRequest): Seq[Node] = {
val appId = request.getParameter("appId")
val stateFuture = (master ? RequestMasterState)(timeout).mapTo[MasterState]
@@ -65,37 +59,73 @@ class MasterWebUI(master: ActorRef) extends Logging {
<li><strong>Description:</strong> app.desc.name</li>
<li><strong>User:</strong> app.desc.user</li>
<li><strong>Cores:</strong>
- {if(app.desc.maxCores == Integer.MAX_VALUE) {
- "Unlimited %s granted".format(app.coresGranted)
- } else {
- "%s (%s granted, %s left)".format(
- app.desc.maxCores,
- app.coresGranted,
- app.coresLeft) }
- }
- }
- </li>
- <li><strong>Memory per Slave:</strong> @app.desc.memoryPerSlave</li>
- <li><strong>Submit Date:</strong> @app.submitDate</li>
- <li><strong>State:</strong> @app.state</li>
- <li><strong><a href={app.appUiUrl}>Application Detail UI</a></strong></li>
- </ul>
- </div>
- </div>
+ {
+ if (app.desc.maxCores == Integer.MAX_VALUE) {
+ "Unlimited %s granted".format(app.coresGranted)
+ } else {
+ "%s (%s granted, %s left)".format(
+ app.desc.maxCores, app.coresGranted, app.coresLeft)
+ }
+ }
+ </li>
+ <li><strong>Memory per Slave:</strong> {app.desc.memoryPerSlave}</li>
+ <li><strong>Submit Date:</strong> {app.submitDate}</li>
+ <li><strong>State:</strong> {app.state}</li>
+ <li><strong><a href={app.appUiUrl}>Application Detail UI</a></strong></li>
+ </ul>
+ </div>
+ </div>
<hr/>
- <!-- Executors -->
+ <!-- Executors -->
<div class="row">
<div class="span12">
<h3> Executor Summary </h3>
<br/>
- @executors_table(app.executors.values.toList) <!-- TODO - convert this -->
+ {executorsTable(app.executors.values.toList)}
</div>
</div>
+ UtilsWebUI.makePage(content, "Application Info: " + app.desc.name)
+ }
+
+ def executorsTable(executors: Seq[ExecutorInfo]): Seq[Node] = {
+ <table class="table table-bordered table-striped table-condensed">
+ <thead>
+ <tr>
+ <th>ExecutorID</th>
+ <th>Worker</th>
+ <th>Cores</th>
+ <th>Memory</th>
+ <th>State</th>
+ <th>Logs</th>
+ </tr>
+ </thead>
+ <tbody>
+ {executors.map(executorRow)}
+ </tbody>
+ </table>
+ }
+ def executorRow(executor: ExecutorInfo): Seq[Node] = {
+ <tr>
+ <td>{executor.id}</td>
+ <td>
+ <a href={executor.worker.webUiAddress}>{executor.worker.id}</a>
+ </td>
+ <td>{executor.cores}</td>
+ <td>{executor.memory}</td>
+ <td>{executor.state}</td>
+ <td>
+ <a href={"%s/log?appId=%s&executorId=%s&logType=stdout"
+ .format(executor.worker.webUiAddress, executor.application.id, executor.id)}>stdout</a>
+ <a href={"%s/log?appId=%s&executorId=%s&logType=stderr"
+ .format(executor.worker.webUiAddress, executor.application.id, executor.id)}>stdout</a>
+ </td>
+ </tr>
}
+ /** Index view listing applications and executors */
def index: Seq[Node] = {
val stateFuture = (master ? RequestMasterState)(timeout).mapTo[MasterState]
val state = Await.result(stateFuture, 3 seconds)
@@ -108,9 +138,12 @@ class MasterWebUI(master: ActorRef) extends Logging {
<li><strong>Workers:</strong>{state.workers.size}</li>
<li><strong>Cores:</strong> {state.workers.map(_.cores).sum}Total,
{state.workers.map(_.coresUsed).sum} Used</li>
- <li><strong>Memory:</strong> {Utils.memoryMegabytesToString(state.workers.map(_.memory).sum)} Total,
+ <li><strong>Memory:</strong>
+ {Utils.memoryMegabytesToString(state.workers.map(_.memory).sum)} Total,
{Utils.memoryMegabytesToString(state.workers.map(_.memoryUsed).sum)} Used</li>
- <li><strong>Applications:</strong> {state.activeApps.size} Running, {state.completedApps.size} Completed </li>
+ <li><strong>Applications:</strong>
+ {state.activeApps.size} Running,
+ {state.completedApps.size} Completed </li>
</ul>
</div>
</div>
@@ -157,17 +190,18 @@ class MasterWebUI(master: ActorRef) extends Logging {
</tr>
</thead>
<tbody>
- {workers.map{ worker =>
- <tr>
- <td>
- <a href={worker.webUiAddress}>{worker.id}</a>
- </td>
- <td>{worker.host}:{worker.port}</td>
- <td>{worker.state}</td>
- <td>{worker.cores} ({worker.coresUsed} Used)</td>
- <td>{Utils.memoryMegabytesToString(worker.memory)}
- ({Utils.memoryMegabytesToString(worker.memoryUsed)} Used)</td>
- </tr>
+ {
+ workers.map{ worker =>
+ <tr>
+ <td>
+ <a href={worker.webUiAddress}>{worker.id}</a>
+ </td>
+ <td>{worker.host}:{worker.port}</td>
+ <td>{worker.state}</td>
+ <td>{worker.cores} ({worker.coresUsed} Used)</td>
+ <td>{Utils.memoryMegabytesToString(worker.memory)}
+ ({Utils.memoryMegabytesToString(worker.memoryUsed)} Used)</td>
+ </tr>
}
}
</tbody>
@@ -189,76 +223,27 @@ class MasterWebUI(master: ActorRef) extends Logging {
</tr>
</thead>
<tbody>
- {apps.map{app =>
- <tr>
- <td>
- <a href={"app?appId=" + app.id}>{app.id}</a>
- </td>
- <td>{app.desc.name}</td>
- <td>
- {app.coresGranted}
- </td>
- <td>{Utils.memoryMegabytesToString(app.desc.memoryPerSlave)}</td>
- <td>{WebUI.formatDate(app.submitDate)}</td>
- <td>{app.desc.user}</td>
- <td>{app.state.toString}</td>
- <td>{WebUI.formatDuration(app.duration)}</td>
- </tr>
+ {
+ apps.map{ app =>
+ <tr>
+ <td>
+ <a href={"app?appId=" + app.id}>{app.id}</a>
+ </td>
+ <td>{app.desc.name}</td>
+ <td>
+ {app.coresGranted}
+ </td>
+ <td>{Utils.memoryMegabytesToString(app.desc.memoryPerSlave)}</td>
+ <td>{WebUI.formatDate(app.submitDate)}</td>
+ <td>{app.desc.user}</td>
+ <td>{app.state.toString}</td>
+ <td>{WebUI.formatDuration(app.duration)}</td>
+ </tr>
+ }
}
- }
</tbody>
</table>
}
-
- /*
- val handler = {
- get {
- (path("") & parameters('format ?)) {
- case Some(js) if js.equalsIgnoreCase("json") =>
- val future = master ? RequestMasterState
- respondWithMediaType(MediaTypes.`application/json`) { ctx =>
- ctx.complete(future.mapTo[MasterState])
- }
- case _ =>
- completeWith {
- val future = master ? RequestMasterState
- future.map {
- masterState => spark.deploy.master.html.index.render(masterState.asInstanceOf[MasterState])
- }
- }
- } ~
- path("app") {
- parameters("appId", 'format ?) {
- case (appId, Some(js)) if (js.equalsIgnoreCase("json")) =>
- val future = master ? RequestMasterState
- val appInfo = for (masterState <- future.mapTo[MasterState]) yield {
- masterState.activeApps.find(_.id == appId).getOrElse({
- masterState.completedApps.find(_.id == appId).getOrElse(null)
- })
- }
- respondWithMediaType(MediaTypes.`application/json`) { ctx =>
- ctx.complete(appInfo.mapTo[ApplicationInfo])
- }
- case (appId, _) =>
- completeWith {
- val future = master ? RequestMasterState
- future.map { state =>
- val masterState = state.asInstanceOf[MasterState]
- val app = masterState.activeApps.find(_.id == appId).getOrElse({
- masterState.completedApps.find(_.id == appId).getOrElse(null)
- })
- spark.deploy.master.html.app_details.render(app)
- }
- }
- }
- } ~
- pathPrefix("static") {
- getFromResourceDirectory(STATIC_RESOURCE_DIR)
- } ~
- getFromResourceDirectory(RESOURCE_DIR)
- }
- }
- */
}
object MasterWebUI {