Skip to content

[SNAP-1240] Snappy monitoring dashboard #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
==========================================================================
SnappyData Custom Styles
==========================================================================
*/


.keyStates{
float: left;
padding: 5px;
margin: 5px 10px;
border: 1px solid #DCDCDC;
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.4);
background: white none repeat scroll 0% 0%;
overflow: visible;
width: 100%;
max-width: 223px;
min-height: 100px;
}

.keyStatesLeft{
float: left;
padding: 5px;
margin: 5px 10px;
border: 1px solid #DCDCDC;
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.4);
background: white none repeat scroll 0% 0%;
overflow: visible;
width: 100%;
max-width: 223px;
min-height: 100px;
}

.keyStatesRight{
float: left;
padding: 5px;
margin: 5px 10px;
border: 1px solid #DCDCDC;
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.4);
background: white none repeat scroll 0% 0%;
overflow: visible;
width: 100%;
max-width: 223px;
min-height: 100px;
}

.keyStatsValue{
padding-bottom: 10px;
font-weight: bolder;
vertical-align: middle;
text-align: center;
padding-top: 25px;
font-size: 24px;
}

.keyStatesText{
font-weight: bolder;
min-height: 25px;
text-align: center;
padding: 10px;
}

.clusterHealthImageBox{
float: left;
width: 94px;
border-right: thin inset;
height: 100px;
}

.clusterHealthTextBox{
text-align: center;
float: left;
width: 200px;}

.statusTextNormal{
color: #87B025;
}
.statusTextWarning{
color: #FDB406;
}
.statusTextError{
color: #FD063A;
}

.divClass2{
}
.div-width-100{
width: 100px;
}
.div-width-200{
width: 200px;
}
.div-width-300{
width: 300px;
}

.progressBar{
height: 19px;
width: 100%;
border-radius: 5px;
border: thin solid #3EC0FF;
background: #A0DFFF none repeat scroll 0 0;
}
.completedProgress{
float: left;
border-radius: inherit;
background: #3EC0FF none repeat scroll 0px 0px;
}
/*
.remainingProgress{
float: left;
border-radius: inherit;
background: #A0DFFF none repeat scroll 0px 0px;
}*/
.progressValue{
float:right;
width:20%;
text-align:center;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions core/src/main/scala/org/apache/spark/ui/SparkUI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package org.apache.spark.ui
import java.util.{Date, ServiceLoader}

import scala.collection.JavaConverters._
import scala.collection.mutable.ArrayBuffer

import org.apache.spark.{SecurityManager, SparkConf, SparkContext}
import org.apache.spark.internal.Logging
Expand All @@ -38,7 +39,7 @@ import org.apache.spark.util.Utils
/**
* Top level user interface for a Spark application.
*/
private[spark] class SparkUI private (
class SparkUI private (
val sc: Option[SparkContext],
val conf: SparkConf,
securityManager: SecurityManager,
Expand Down Expand Up @@ -71,7 +72,7 @@ private[spark] class SparkUI private (
attachTab(new EnvironmentTab(this))
attachTab(new ExecutorsTab(this))
attachHandler(createStaticHandler(SparkUI.STATIC_RESOURCE_DIR, "/static"))
attachHandler(createRedirectHandler("/", "/jobs/", basePath = basePath))
// attachHandler(createRedirectHandler("/", "/jobs/", basePath = basePath))
attachHandler(ApiRootResource.getServletHandler(this))
// This should be POST only, but, the YARN AM proxy won't proxy POSTs
attachHandler(createRedirectHandler(
Expand All @@ -90,6 +91,10 @@ private[spark] class SparkUI private (
appId = id
}

def setTabs(newTabs: ArrayBuffer[WebUITab]): Unit = {
tabs = newTabs
}

/** Stop the server behind this web interface. Only valid after bind(). */
override def stop() {
super.stop()
Expand Down
49 changes: 48 additions & 1 deletion core/src/main/scala/org/apache/spark/ui/UIUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ private[spark] object UIUtils extends Logging {
<link rel="stylesheet" href={prependBaseUri("/static/vis.min.css")} type="text/css"/>
<link rel="stylesheet" href={prependBaseUri("/static/webui.css")} type="text/css"/>
<link rel="stylesheet" href={prependBaseUri("/static/timeline-view.css")} type="text/css"/>
<link rel="stylesheet" href={prependBaseUri("/static/snappy-dashboard.css")} type="text/css"/>
<script src={prependBaseUri("/static/sorttable.js")} ></script>
<script src={prependBaseUri("/static/jquery-1.11.1.min.js")}></script>
<script src={prependBaseUri("/static/vis.min.js")}></script>
Expand Down Expand Up @@ -222,7 +223,7 @@ private[spark] object UIUtils extends Logging {
<div class="navbar-inner">
<div class="brand">
<a href={prependBaseUri("/")} class="brand">
<img src={prependBaseUri("/static/spark-logo-77x50px-hd.png")} />
<img src={prependBaseUri("/static/snappydata/SnappyData-Logo-230X50.png")} />
<span class="version">{org.apache.spark.SPARK_VERSION}</span>
</a>
</div>
Expand All @@ -247,6 +248,52 @@ private[spark] object UIUtils extends Logging {
</html>
}

/** Returns a simple spark page with correctly formatted tabs */
def simpleSparkPageWithTabs(
title: String,
content: => Seq[Node],
activeTab: SparkUITab,
refreshInterval: Option[Int] = None,
helpText: Option[String] = None,
showVisualization: Boolean = false): Seq[Node] = {

val appName = activeTab.appName
val shortAppName = if (appName.length < 36) appName else appName.take(32) + "..."
val header = activeTab.headerTabs.map { tab =>
<li class={if (tab == activeTab) "active" else ""}>
<a href={prependBaseUri(activeTab.basePath, "/" + tab.prefix + "/")}>{tab.name}</a>
</li>
}
// val helpButton: Seq[Node] = helpText.map(tooltip(_, "bottom")).getOrElse(Seq.empty)

<html>
<head>
{commonHeaderNodes}
{if (showVisualization) vizHeaderNodes else Seq.empty}
<title>{appName} - {title}</title>
</head>
<body>
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="brand">
<a href={prependBaseUri("/")} class="brand">
<img src={prependBaseUri("/static/snappydata/SnappyData-Logo-230X50.png")} />
<span class="version">{org.apache.spark.SPARK_VERSION}</span>
</a>
</div>
<p class="navbar-text pull-right">
<strong title={appName}>{shortAppName}</strong> application UI
</p>
<ul class="nav">{header}</ul>
</div>
</div>
<div class="container-fluid">
{content}
</div>
</body>
</html>
}

/** Returns a page with the spark css/js and a simple format. Used for scheduler UI. */
def basicSparkPage(
content: => Seq[Node],
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/org/apache/spark/ui/WebUI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private[spark] abstract class WebUI(
name: String = "")
extends Logging {

protected val tabs = ArrayBuffer[WebUITab]()
protected var tabs = ArrayBuffer[WebUITab]()
protected val handlers = ArrayBuffer[ServletContextHandler]()
protected val pageToHandlers = new HashMap[WebUIPage, ArrayBuffer[ServletContextHandler]]
protected var serverInfo: Option[ServerInfo] = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private[ui] class StoragePage(parent: StorageTab) extends WebUIPage("") {
def render(request: HttpServletRequest): Seq[Node] = {
val content = rddTable(listener.rddInfoList) ++
receiverBlockTables(listener.allExecutorStreamBlockStatus.sortBy(_.executorId))
UIUtils.headerSparkPage("Storage", content, parent)
UIUtils.headerSparkPage("Spark Cache", content, parent)
}

private[storage] def rddTable(rdds: Seq[RDDInfo]): Seq[Node] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.apache.spark.storage._
import org.apache.spark.ui._

/** Web UI showing storage status of all RDD's in the given SparkContext. */
private[ui] class StorageTab(parent: SparkUI) extends SparkUITab(parent, "storage") {
private[ui] class StorageTab(parent: SparkUI) extends SparkUITab(parent, "Spark Cache") {
val listener = parent.storageListener

attachPage(new StoragePage(this))
Expand Down