eagle-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jjt...@apache.org
Subject eagle git commit: [EAGLE-953] Host-level Overview Heatmap Diagram for Topology Monitoring
Date Thu, 13 Apr 2017 06:20:20 GMT
Repository: eagle
Updated Branches:
  refs/heads/master 4ff4d628f -> 01553a346


[EAGLE-953] Host-level Overview Heatmap Diagram for Topology Monitoring

https://issues.apache.org/jira/browse/EAGLE-953

Author: koone <luokun1028@126.com>

Closes #907 from koone/heatmap.


Project: http://git-wip-us.apache.org/repos/asf/eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/eagle/commit/01553a34
Tree: http://git-wip-us.apache.org/repos/asf/eagle/tree/01553a34
Diff: http://git-wip-us.apache.org/repos/asf/eagle/diff/01553a34

Branch: refs/heads/master
Commit: 01553a34639423621b534bc9837dea4cf4c71b4b
Parents: 4ff4d62
Author: koone <luokun1028@126.com>
Authored: Thu Apr 13 06:20:05 2017 +0000
Committer: r7raul1984 <tangjijun@yhd.com>
Committed: Thu Apr 13 06:20:05 2017 +0000

----------------------------------------------------------------------
 .../apps/hbase/ctrls/backupMasterListCtrl.js    | 124 ++++++++++++++++++-
 .../app/apps/hbase/ctrls/regionListCtrl.js      | 124 ++++++++++++++++++-
 .../src/main/webapp/app/apps/hbase/index.js     |  18 ++-
 .../apps/hbase/partials/backupMasterList.html   |  85 ++++++++-----
 .../apps/hbase/partials/region/regionList.html  |  88 ++++++++-----
 .../app/apps/hdfs/ctrl/datanodeListCtrl.js      | 118 +++++++++++++++++-
 .../app/apps/hdfs/ctrl/namenodeListCtrl.js      | 120 +++++++++++++++++-
 .../app/apps/hdfs/partials/datanodeList.html    |  88 ++++++++-----
 .../app/apps/hdfs/partials/namenodeList.html    |  88 ++++++++-----
 .../webapp/app/apps/hdfs/partials/overview.html |   4 +-
 10 files changed, 711 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/backupMasterListCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/backupMasterListCtrl.js
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/backupMasterListCtrl.js
index ca6c47e..2330885 100644
--- a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/backupMasterListCtrl.js
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/backupMasterListCtrl.js
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *	 http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -30,6 +30,128 @@
 			$scope.site = $wrapState.param.siteId;
 			$scope.searchPathList = [["tags", "hostname"], ["tags", "rack"], ["tags", "site"], ["status"]];
 			$scope.backupMasterList = METRIC.hbaseMaster($scope.site, "standby", 1000);
+
+			$scope.masterAll = METRIC.hbaseMaster($scope.site);
+
+
+			function getCommonHeatMapSeries(name, data) {
+				return {
+					name: name,
+					type: 'heatmap',
+					data: data,
+					label: {
+						normal: {
+							show: true,
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3];
+								}
+								return "";
+							}
+						}
+					},
+					itemStyle: {
+						normal: {
+							borderColor: "#FFF"
+						},
+						emphasis: {
+							shadowBlur: 10,
+							shadowColor: 'rgba(0, 0, 0, 0.5)'
+						}
+					}
+				};
+			}
+
+			function getCommonHeatMapOption() {
+				return {
+					animation: false,
+					tooltip: {
+						trigger: 'item'
+					},
+					xAxis: {
+						show: false,
+						data: [0,-1,-2,-3,-4],
+						splitArea: {show: true}
+					},
+					yAxis: [{
+						show: false,
+						splitArea: {show: true},
+						axisTick: {show: false}
+					}],
+					grid: {
+						left: "1%",
+						right: "1%",
+						top: "60",
+						bottom: "60"
+					},
+					visualMap: {
+						categories: ['active', 'standby'],
+						calculable: true,
+						orient: 'horizontal',
+						right: "2%",
+						inRange: {
+							color: ['#00a65a', '#dd4b39']
+						}
+					}
+				};
+			}
+
+
+			// region server heatmap chart
+			$scope.masterAll._promise.then(function () {
+				var master_status = [];
+				var master_status_category = [];
+				var x = -1;
+				var y = 0;
+				var split = 5;
+				$.each($scope.masterAll,
+					/**
+					 * @param {number} i
+					 * @param {RegionServer} master
+					 */
+					function (i, master) {
+						if(x === split){
+							x = 0;
+							y = y - 1;
+						}else{
+							x = x +1;
+						}
+						master_status.push([x, y, 0, master.tags.hostname, master.tags.rack, master.status
|| "-"])
+					});
+				for(var i = 0;i < split; i++){
+					master_status_category.push(i);
+				}
+				$scope.healthStatusSeries = [getCommonHeatMapSeries("Health", master_status)];
+				console.log($scope.healthStatusSeries);
+				$scope.healthStatusOption = getHealthHeatMapOption();
+				console.log($scope.healthStatusOption);
+				$scope.healthStatusCategory = master_status_category;
+				$scope.heatmapHeight = {
+					'height': getHeight(y)
+				};
+
+				function getHeight(x){
+					return (Math.abs(x-1)*30 + 140) + "px"
+				}
+
+				function getHealthHeatMapOption() {
+					var option = getCommonHeatMapOption();
+					return common.merge(option, {
+						tooltip: {
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3] + '<br/>'
+									+ 'status: <span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
+ point.color + '"></span> ' + point.data[5] + '<br/>'
+									+ 'rack: ' +  point.data[4] + '<br/>';
+								}
+								return "";
+							}
+						}
+					});
+				}
+
+			});
+
 		});
 	});
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
index 6fc9ab0..401ef15 100644
--- a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/ctrls/regionListCtrl.js
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *	 http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -33,6 +33,128 @@
 			$scope.status = $wrapState.param.status;
 			$scope.searchPathList = [["tags", "hostname"], ["tags", "rack"], ["tags", "site"], ["status"]];
 			$scope.regionserverList = METRIC.regionserverList($scope.site, $scope.status);
+			$scope.regionserverAll = METRIC.regionserverList($scope.site);
+
+
+			function getCommonHeatMapSeries(name, data) {
+				return {
+					name: name,
+					type: 'heatmap',
+					data: data,
+					label: {
+						normal: {
+							show: true,
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3];
+								}
+								return "";
+							}
+						}
+					},
+					itemStyle: {
+						normal: {
+							borderColor: "#FFF"
+						},
+						emphasis: {
+							shadowBlur: 10,
+							shadowColor: 'rgba(0, 0, 0, 0.5)'
+						}
+					}
+				};
+			}
+
+			function getCommonHeatMapOption() {
+				return {
+					animation: false,
+					tooltip: {
+						trigger: 'item'
+					},
+					grid: {
+							left: "1%",
+							right: "1%",
+							top: "60",
+							bottom: "60"
+					},
+					xAxis: {
+						show: false,
+						splitArea: {show: true}
+					},
+					yAxis: [{
+						show: false,
+						splitArea: {show: true},
+						axisTick: {show: false}
+					}],
+					visualMap: {
+						categories: ['live', 'dead'],
+						calculable: true,
+						orient: 'horizontal',
+						right: "2%",
+						inRange: {
+							color: ['#00a65a', '#dd4b39']
+						}
+					}
+				};
+			}
+
+
+			// region server heatmap chart
+			$scope.regionserverAll._promise.then(function () {
+				var regionServer_status = [];
+				var regionServer_status_category = [];
+				var regionServer_level = [];
+				var x = -1;
+				var y = 0;
+				var split = 5;
+				$.each($scope.regionserverAll,
+				/**
+				 * @param {number} i
+				 * @param {RegionServer} regionServer
+				 */
+				function (i, regionServer) {
+					if(x === split){
+						x = 0;
+						y = y - 1;
+					}else{
+						x = x +1;
+					}
+					regionServer_status.push([x, y, 0, regionServer.tags.hostname, regionServer.tags.rack,
regionServer.usedHeapMB, regionServer.maxHeapMB, regionServer.status || "-"]);
+				});
+				
+				for(var i = 0;i < split; i++){
+					regionServer_status_category.push(i);
+				}
+				$scope.healthStatusSeries = [getCommonHeatMapSeries("Health", regionServer_status)];
+				$scope.healthStatusOption = getHealthHeatMapOption();
+				$scope.healthStatusCategory = regionServer_status_category;
+				$scope.heatmapHeight = {
+					'height': getHeight(y)
+				};
+
+				function getHeight(x){
+					return (Math.abs(x-1)*30 + 140) + "px"
+				}
+
+				function getHealthHeatMapOption() {
+					var option = getCommonHeatMapOption();
+					return common.merge(option, {
+						tooltip: {
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3] + '<br/>'
+									+ 'status: <span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
+ point.color + '"></span> ' + point.data[7] + '<br/>'
+									+ 'rack: ' +  point.data[4] + '<br/>'
+									+ 'heap used: ' +  point.data[5] + '/' +  point.data[6] + ' MB<br/>';
+								}
+								return "";
+							}
+						}
+					});
+				}
+
+			});
 		});
+
+
 	});
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
index 8e4ea46..157cded 100644
--- a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/index.js
@@ -283,11 +283,19 @@
 		};
 
 		METRIC.hbaseMaster = function (siteId, status, limit) {
-			var condition = {
-				site: siteId,
-				role: "hmaster",
-				status: status
-			};
+			var condition = {};
+			if(typeof status === 'undefined') {
+				condition = {
+					site: siteId,
+					role: "hmaster"
+				};
+			} else {
+				condition = {
+					site: siteId,
+					role: "hmaster",
+					status: status
+				};
+			}
 			return METRIC.hbasehostStatus(condition, limit);
 		};
 

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
index 13e20c9..e35aae3 100644
--- a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/backupMasterList.html
@@ -15,38 +15,57 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<div class="box box-primary">
-	<div class="box-header with-border">
-		<h3 class="box-title">
-			<span ng-show="!backupMasterList._done || isSorting" class="fa fa-refresh fa-spin no-animate"></span>
-		</h3>
-	</div>
-	<div class="box-body">
-		<div id="backupMasterList" sort-table="backupMasterList" is-sorting="isSorting"
-			 search-path-list="searchPathList"
-			 scope="tableScope">
-			<table class="table table-bordered">
-				<thead>
-				<tr>
-					<th sortpath="tags.hostname">Master</th>
-					<th sortpath="tags.rack">Rack</th>
-					<th sortpath="tags.site">SiteId</th>
-					<th sortpath="status">Status</th>
-				</tr>
-				</thead>
-				<tbody>
-				<tr ng-repeat="item in backupMasterList">
-					<td>
-						<a ui-sref="masterDetail({siteId: site, hostname: item.tags.hostname})">{{item.tags.hostname}}</a>
-					</td>
-					<td>{{item.tags.rack}}</td>
-					<td>{{item.tags.site}}</td>
-					<td>
-						<span>{{item.status}}</span>
-					</td>
-				</tr>
-				</tbody>
-			</table>
+<div class="nav-tabs-custom" style="cursor: move;">
+	<ul class="nav nav-tabs pull-right ui-sortable-handle">
+      <li><a href="#heatmap" data-toggle="tab" aria-expanded="false" ng-click="healthHeatMap.resize()">HeatMap</a></li>
+      <li class="active"><a href="#list" data-toggle="tab" aria-expanded="true">List</a></li>
+    </ul>
+
+    <div class="tab-content no-padding keepContent">
+    	<div class="box box-primary no-margin tab-pane fade in active" id="list">
+			<div class="box-body">
+				<div id="backupMasterList" sort-table="backupMasterList" is-sorting="isSorting"
+					 search-path-list="searchPathList"
+					 scope="tableScope">
+					<table class="table table-bordered">
+						<thead>
+						<tr>
+							<th sortpath="tags.hostname">Master</th>
+							<th sortpath="tags.rack">Rack</th>
+							<th sortpath="tags.site">SiteId</th>
+							<th sortpath="status">Status</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr ng-repeat="item in backupMasterList">
+							<td>
+								<a ui-sref="masterDetail({siteId: site, hostname: item.tags.hostname})">{{item.tags.hostname}}</a>
+							</td>
+							<td>{{item.tags.rack}}</td>
+							<td>{{item.tags.site}}</td>
+							<td>
+								<span>{{item.status}}</span>
+							</td>
+						</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+
+
+		<!--region server health chart-->
+		<div class="box box-primary no-margin tab-pane fade" id="heatmap">
+			<div class="box-body">
+				<div class="hadoopMetric-chart">
+					<div chart="healthHeatMap" ng-style="heatmapHeight" series="healthStatusSeries" category="healthStatusCategory"
option="healthStatusOption"></div>
+					<div ng-if="(healthStatusSeries || []).length === 0" class="overlay">
+						<i class="fa fa-refresh fa-spin"></i>
+					</div>
+				</div>
+			</div>
 		</div>
-	</div>
+
+    </div>
+
 </div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
index d1a7440..dd78c3b 100644
--- a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
+++ b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/partials/region/regionList.html
@@ -15,39 +15,59 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<div class="box box-primary">
-	<div class="box-header with-border">
-		<h3 class="box-title">
-			<span ng-show="!regionserverList._done || isSorting" class="fa fa-refresh fa-spin no-animate"></span>
-		</h3>
-	</div>
-	<div class="box-body">
-		<div id="regionserverList" sort-table="regionserverList" is-sorting="isSorting"
-			 search-path-list="searchPathList"
-			 scope="tableScope">
-			<table class="table table-bordered">
-				<thead>
-				<tr>
-					<th sortpath="tags.hostname">RegionServer</th>
-					<th sortpath="tags.rack">Rack</th>
-					<th sortpath="tags.site">SiteId</th>
-					<th sortpath="status">Status</th>
-				</tr>
-				</thead>
-				<tbody>
-				<tr ng-repeat="item in regionserverList">
-					<td>
-						<a ui-sref="regionDetail({siteId: site, hostname: item.tags.hostname})">{{item.tags.hostname}}</a>
-					</td>
-					<td>{{item.tags.rack}}</td>
-					<td>{{item.tags.site}}</td>
-					<td>
-						<span ng-if="item.status===live" class="label label-success">Healthy</span>
-						<span ng-if="item.status===dead" class="label label-danger">UnHealthy</span>
-					</td>
-				</tr>
-				</tbody>
-			</table>
+<div class="nav-tabs-custom" style="cursor: move;">
+	<ul class="nav nav-tabs pull-right ui-sortable-handle">
+      <li><a href="#heatmap" data-toggle="tab" aria-expanded="false" ng-click="healthHeatMap.resize()">HeatMap</a></li>
+      <li class="active"><a href="#list" data-toggle="tab" aria-expanded="true">List</a></li>
+    </ul>
+
+    <div class="tab-content no-padding keepContent">
+    	<div class="box box-primary no-margin tab-pane fade in active" id="list">
+			<div class="box-body">
+				<div id="regionserverList" sort-table="regionserverList" is-sorting="isSorting"
+					 search-path-list="searchPathList"
+					 scope="tableScope">
+					<table class="table table-bordered">
+						<thead>
+						<tr>
+							<th sortpath="tags.hostname">RegionServer</th>
+							<th sortpath="tags.rack">Rack</th>
+							<th sortpath="tags.site">SiteId</th>
+							<th sortpath="status">Status</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr ng-repeat="item in regionserverList">
+							<td>
+								<a ui-sref="regionDetail({siteId: site, hostname: item.tags.hostname})">{{item.tags.hostname}}</a>
+							</td>
+							<td>{{item.tags.rack}}</td>
+							<td>{{item.tags.site}}</td>
+							<td>
+								<span ng-if="item.status===live" class="label label-success">Healthy</span>
+								<span ng-if="item.status===dead" class="label label-danger">UnHealthy</span>
+							</td>
+						</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+
+
+		<!--region server health chart-->
+		<div class="box box-primary no-margin tab-pane fade" id="heatmap">
+			<div class="box-body">
+				<div class="hadoopMetric-chart">
+					<div chart="healthHeatMap" ng-style="heatmapHeight" series="healthStatusSeries" category="healthStatusCategory"
option="healthStatusOption"></div>
+					<div ng-if="(healthStatusSeries || []).length === 0" class="overlay">
+						<i class="fa fa-refresh fa-spin"></i>
+					</div>
+				</div>
+			</div>
 		</div>
-	</div>
+
+    </div>
+
 </div>
+

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
index 78ea7e1..7664b7c 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *	 http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -35,6 +35,122 @@
 			$scope.datanodeList = (typeof $scope.status === 'undefined') ? HDFSMETRIC.getListByRoleName("HdfsServiceInstance",
"datanode", $scope.site)
 			   : HDFSMETRIC.getHadoopHostByStatusAndRole("HdfsServiceInstance", $scope.site, $scope.status,
"datanode");
 
+			$scope.datanodeAll = HDFSMETRIC.getListByRoleName("HdfsServiceInstance", "datanode", $scope.site);
+
+
+			function getCommonHeatMapSeries(name, data) {
+				return {
+					name: name,
+					type: 'heatmap',
+					data: data,
+					label: {
+						normal: {
+							show: true,
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3];
+								}
+								return "";
+							}
+						}
+					},
+					itemStyle: {
+						normal: {
+							borderColor: "#FFF"
+						},
+						emphasis: {
+						shadowBlur: 10,
+							shadowColor: 'rgba(0, 0, 0, 0.5)'
+						}
+					}
+				};
+			}
+
+			function getCommonHeatMapOption() {
+				return {
+					animation: false,
+					tooltip: {
+						trigger: 'item'
+					},
+					xAxis: {
+						show: false,
+						splitArea: {show: true}
+					},
+					yAxis: [{
+						show: false,
+						splitArea: {show: true},
+						axisTick: {show: false}
+					}],
+					grid: {
+						left: "1%",
+						right: "1%",
+						top: "60",
+						bottom: "60"
+					},
+					visualMap: {
+						categories: ['live', 'dead'],
+						calculable: true,
+						orient: 'horizontal',
+						right: "2%",
+						inRange: {
+							color: ['#00a65a', '#dd4b39']
+						}
+					}
+				};
+			}
+
+
+			// region server heatmap chart
+			$scope.datanodeAll._promise.then(function () {
+				var datanode_status = [];
+				var datanode_status_category = [];
+				var x = -1;
+				var y = 0;
+				var split = 5;
+				$.each($scope.datanodeAll,
+					/**
+					 * @param {number} i
+					 * @param {RegionServer} datanode
+					 */
+					function (i, datanode) {
+						if(x === split){
+							x = 0;
+							y = y - 1;
+						}else{
+							x = x +1;
+						}
+						datanode_status.push([x, y, 0, datanode.tags.hostname, datanode.tags.rack, datanode.status
|| "-"])
+					});
+				for(var i = 0;i < split; i++){
+					datanode_status_category.push(i);
+				}
+				$scope.healthStatusSeries = [getCommonHeatMapSeries("Health", datanode_status)];
+				$scope.healthStatusOption = getHealthHeatMapOption();
+				$scope.healthStatusCategory = datanode_status_category;
+				$scope.heatmapHeight = {
+					'height': getHeight(y)
+				};
+				function getHeight(x){
+					return (Math.abs(x-1)*30 + 140) + "px"
+				}
+
+				function getHealthHeatMapOption() {
+					var option = getCommonHeatMapOption();
+					return common.merge(option, {
+						tooltip: {
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3] + '<br/>'
+									+ 'status: <span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
+ point.color + '"></span> ' + point.data[5] + '<br/>'
+									+ 'rack: ' +  point.data[4] + '<br/>';
+								}
+								return "";
+							}
+						}
+					});
+				}
+
+			});
 		});
 	});
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
index 8424b8e..d0d41bf 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
@@ -7,7 +7,7 @@
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *	 http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -32,6 +32,124 @@
 			$scope.searchPathList = [["tags", "hostname"], ["tags", "rack"], ["tags", "site"], ["status"]];
 			$scope.namenodeList = (typeof $scope.status === 'undefined') ? HDFSMETRIC.getListByRoleName("HdfsServiceInstance",
"namenode", $scope.site)
 				: HDFSMETRIC.getHadoopHostByStatusAndRole("HdfsServiceInstance", $scope.site, $scope.status,
"namenode");
+
+			$scope.namenodeAll = HDFSMETRIC.getListByRoleName("HdfsServiceInstance", "namenode", $scope.site);
+
+
+			function getCommonHeatMapSeries(name, data) {
+				return {
+					name: name,
+					type: 'heatmap',
+					data: data,
+					label: {
+						normal: {
+							show: true,
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3];
+								}
+								return "";
+							}
+						}
+					},
+					itemStyle: {
+						normal: {
+							borderColor: "#FFF"
+						},
+						emphasis: {
+							shadowBlur: 10,
+							shadowColor: 'rgba(0, 0, 0, 0.5)'
+						}
+					}
+				};
+			}
+
+			function getCommonHeatMapOption() {
+				return {
+					animation: false,
+					tooltip: {
+						trigger: 'item'
+					},
+					xAxis: {
+						show: false,
+						splitArea: {show: true}
+					},
+					yAxis: [{
+						show: false,
+						splitArea: {show: true},
+						axisTick: {show: false}
+					}],
+					grid: {
+						left: "1%",
+						right: "1%",
+						top: "60",
+						bottom: "60"
+					},
+					visualMap: {
+						categories: ['active', 'standby'],
+						calculable: true,
+						orient: 'horizontal',
+						right: "2%",
+						inRange: {
+							color: ['#00a65a', '#dd4b39']
+						}
+					}
+				};
+			}
+
+
+			// region server heatmap chart
+			$scope.namenodeAll._promise.then(function () {
+				var namenode_status = [];
+				var namenode_status_category = [];
+				var x = -1;
+				var y = 0;
+				var split = 5;
+				$.each($scope.namenodeAll,
+					/**
+					 * @param {number} i
+					 * @param {RegionServer} namenode
+					 */
+					function (i, namenode) {
+						if(x === split){
+							x = 0;
+							y = y - 1;
+						}else{
+							x = x +1;
+						}
+						namenode_status.push([x, y, 0, namenode.tags.hostname, namenode.tags.rack, namenode.usedCapacityTB,
namenode.status || "-"])
+					});
+				for(var i = 0;i < split; i++){
+					namenode_status_category.push(i);
+				}
+				$scope.healthStatusSeries = [getCommonHeatMapSeries("Health", namenode_status)];
+				$scope.healthStatusOption = getHealthHeatMapOption();
+				$scope.healthStatusCategory = namenode_status_category;
+				$scope.heatmapHeight = {
+					'height': getHeight(y)
+				};
+				function getHeight(x){
+					return (Math.abs(x-1)*30 + 140) + "px"
+				}
+
+				function getHealthHeatMapOption() {
+					var option = getCommonHeatMapOption();
+					return common.merge(option, {
+						tooltip: {
+							formatter: function (point) {
+								if(point.data) {
+									return point.data[3] + '<br/>'
+									+ 'status: <span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
+ point.color + '"></span> ' + point.data[6] + '<br/>'
+									+ 'rack: ' +  point.data[4] + '<br/>'
+									+ 'usedCapacity: ' +  point.data[5] + ' TB<br/>';
+								}
+								return "";
+							}
+						}
+					});
+				}
+
+			});
 		});
 	});
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
index b76d44d..a53251e 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
@@ -15,39 +15,59 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<div class="box box-primary">
-	<div class="box-header with-border">
-		<h3 class="box-title">
-			<span ng-show="!datanodeList._done || isSorting" class="fa fa-refresh fa-spin no-animate"></span>
-		</h3>
-	</div>
-	<div class="box-body">
-		<div id="datanodeList" sort-table="datanodeList" is-sorting="isSorting"
-			 search-path-list="searchPathList"
-			 scope="tableScope">
-			<table class="table table-bordered">
-				<thead>
-				<tr>
-					<th sortpath="tags.hostname">Datanode</th>
-					<th sortpath="tags.rack">Rack</th>
-					<th sortpath="tags.site">SiteId</th>
-					<th sortpath="status">Status</th>
-				</tr>
-				</thead>
-				<tbody>
-				<tr ng-repeat="item in datanodeList">
-					<td>
-						<a ui-sref="datanodeDetail({siteId: site, hostname: item.tags.hostname})" target="_blank">{{item.tags.hostname}}</a>
-					</td>
-					<td>{{item.tags.rack}}</td>
-					<td>{{item.tags.site}}</td>
-					<td>
-						<span ng-if="item.status===live" class="label label-success">Healthy</span>
-						<span ng-if="item.status===dead" class="label label-danger">UnHealthy</span>
-					</td>
-				</tr>
-				</tbody>
-			</table>
+
+<div class="nav-tabs-custom" style="cursor: move;">
+	<ul class="nav nav-tabs pull-right ui-sortable-handle">
+      <li><a href="#heatmap" data-toggle="tab" aria-expanded="false" ng-click="healthHeatMap.resize()">HeatMap</a></li>
+      <li class="active"><a href="#list" data-toggle="tab" aria-expanded="true">List</a></li>
+    </ul>
+
+    <div class="tab-content no-padding keepContent">
+    	<div class="box box-primary no-margin tab-pane fade in active" id="list">
+			<div class="box-body">
+				<div id="datanodeList" sort-table="datanodeList" is-sorting="isSorting"
+					 search-path-list="searchPathList"
+					 scope="tableScope">
+					<table class="table table-bordered">
+						<thead>
+						<tr>
+							<th sortpath="tags.hostname">Datanode</th>
+							<th sortpath="tags.rack">Rack</th>
+							<th sortpath="tags.site">SiteId</th>
+							<th sortpath="status">Status</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr ng-repeat="item in datanodeList">
+							<td>
+								<a ui-sref="datanodeDetail({siteId: site, hostname: item.tags.hostname})" target="_blank">{{item.tags.hostname}}</a>
+							</td>
+							<td>{{item.tags.rack}}</td>
+							<td>{{item.tags.site}}</td>
+							<td>
+								<span ng-if="item.status===live" class="label label-success">Healthy</span>
+								<span ng-if="item.status===dead" class="label label-danger">UnHealthy</span>
+							</td>
+						</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
 		</div>
-	</div>
+
+
+		<!--region server health chart-->
+		<div class="box box-primary no-margin tab-pane fade" id="heatmap">
+			<div class="box-body">
+				<div class="hadoopMetric-chart">
+					<div chart="healthHeatMap" ng-style="heatmapHeight" series="healthStatusSeries" category="healthStatusCategory"
option="healthStatusOption"></div>
+					<div ng-if="(healthStatusSeries || []).length === 0" class="overlay">
+						<i class="fa fa-refresh fa-spin"></i>
+					</div>
+				</div>
+			</div>
+		</div>
+
+    </div>
+
 </div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
index d10aa0b..d9bab1a 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
@@ -15,38 +15,58 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<div class="box box-primary">
-	<div class="box-header with-border">
-		<h3 class="box-title">
-			<span ng-show="!namenodeList._done || isSorting" class="fa fa-refresh fa-spin no-animate"></span>
-		</h3>
-	</div>
-	<div class="box-body">
-		<div id="namenodeList" sort-table="namenodeList" is-sorting="isSorting"
-			 search-path-list="searchPathList"
-			 scope="tableScope">
-			<table class="table table-bordered">
-				<thead>
-				<tr>
-					<th sortpath="tags.hostname">Namenode</th>
-					<th sortpath="tags.rack">Rack</th>
-					<th sortpath="tags.site">SiteId</th>
-					<th sortpath="status">Status</th>
-				</tr>
-				</thead>
-				<tbody>
-				<tr ng-repeat="item in namenodeList">
-					<td>
-						<a ui-sref="namenodeDetail({siteId: site, hostname: item.tags.hostname})" target="_blank">{{item.tags.hostname}}</a>
-					</td>
-					<td>{{item.tags.rack}}</td>
-					<td>{{item.tags.site}}</td>
-					<td>
-						<span>{{item.status}}</span>
-					</td>
-				</tr>
-				</tbody>
-			</table>
+
+<div class="nav-tabs-custom" style="cursor: move;">
+	<ul class="nav nav-tabs pull-right ui-sortable-handle">
+      <li><a href="#heatmap" data-toggle="tab" aria-expanded="false" ng-click="healthHeatMap.resize()">HeatMap</a></li>
+      <li class="active"><a href="#list" data-toggle="tab" aria-expanded="true">List</a></li>
+    </ul>
+
+    <div class="tab-content no-padding keepContent">
+    	<div class="box box-primary no-margin tab-pane fade in active" id="list">
+			<div class="box-body">
+				<div id="namenodeList" sort-table="namenodeList" is-sorting="isSorting"
+					 search-path-list="searchPathList"
+					 scope="tableScope">
+					<table class="table table-bordered">
+						<thead>
+						<tr>
+							<th sortpath="tags.hostname">Namenode</th>
+							<th sortpath="tags.rack">Rack</th>
+							<th sortpath="tags.site">SiteId</th>
+							<th sortpath="status">Status</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr ng-repeat="item in namenodeList">
+							<td>
+								<a ui-sref="namenodeDetail({siteId: site, hostname: item.tags.hostname})" target="_blank">{{item.tags.hostname}}</a>
+							</td>
+							<td>{{item.tags.rack}}</td>
+							<td>{{item.tags.site}}</td>
+							<td>
+								<span>{{item.status}}</span>
+							</td>
+						</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
 		</div>
-	</div>
-</div>
+
+
+		<!--region server health chart-->
+		<div class="box box-primary no-margin tab-pane fade" id="heatmap">
+			<div class="box-body">
+				<div class="hadoopMetric-chart">
+					<div chart="healthHeatMap" ng-style="heatmapHeight" series="healthStatusSeries" category="healthStatusCategory"
option="healthStatusOption"></div>
+					<div ng-if="(healthStatusSeries || []).length === 0" class="overlay">
+						<i class="fa fa-refresh fa-spin"></i>
+					</div>
+				</div>
+			</div>
+		</div>
+
+    </div>
+
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/eagle/blob/01553a34/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
index 7a6d9ad..52f8e92 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/overview.html
@@ -28,7 +28,7 @@
             <tr>
                 <td width="5%">
                     <span ng-show="!namenodeactivenum">0</span>
-                    <span ng-show="namenodeactivenum!==-1"><a ui-sref="namenodeList({siteId:
site, status: 'active'})" target="_blank">{{namenodeactivenum}}</a></span>
+                    <span ng-show="namenodeactivenum!==-1"><a ui-sref="namenodeList({siteId:
site, status: 'active'})">{{namenodeactivenum}}</a></span>
                     <span ng-show="namenodeactivenum===-1">N/A</span>
                 </td>
                 <th width="30%">Active Namenode</th>
@@ -46,7 +46,7 @@
             </tr>
             <tr>
                 <td>
-                    <span ng-show="namenodestandbynum!==-1"><a ui-sref="namenodeList({siteId:
site, status: 'standby'})" target="_blank">{{namenodestandbynum}}</a></span>
+                    <span ng-show="namenodestandbynum!==-1"><a ui-sref="namenodeList({siteId:
site, status: 'standby'})">{{namenodestandbynum}}</a></span>
                     <span ng-show="!namenodestandbynum">0</span>
                     <span ng-show="namenodestandbynum===-1">N/A</span>
                 </td>


Mime
View raw message