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 <[email protected]>

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 <[email protected]>
Authored: Thu Apr 13 06:20:05 2017 +0000
Committer: r7raul1984 <[email protected]>
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>

Reply via email to