Repository: eagle
Updated Branches:
  refs/heads/master 86eed4f56 -> 610b9f2ec


[EAGLE-908] Hdfs JMX Monitoring Dashboard

[EAGLE-908] Hdfs JMX Monitoring Dashboard
- Hdfs overview page, use tab to show multiple active namenode, hdfs summary is 
displayed at the upper portion of the page.

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

Author: chitin <[email protected]>

Closes #836 from chitin/eagle908-2.


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

Branch: refs/heads/master
Commit: 610b9f2ecc1221c6aee2243615860a86a3e16593
Parents: 86eed4f
Author: chitin <[email protected]>
Authored: Wed Feb 22 20:58:08 2017 +0800
Committer: Hao Chen <[email protected]>
Committed: Wed Feb 22 20:58:08 2017 +0800

----------------------------------------------------------------------
 .../app/apps/hbase/widgets/availabilityChart.js |   8 +-
 .../src/main/webapp/app/apps/hdfs/config.json   |  34 +++
 .../app/apps/hdfs/ctrl/datanodeDetailCtrl.js    | 221 ++++++++++++++
 .../app/apps/hdfs/ctrl/datanodeListCtrl.js      |  38 +++
 .../app/apps/hdfs/ctrl/namenodeListCtrl.js      |  35 +++
 .../main/webapp/app/apps/hdfs/ctrl/overview.js  | 263 ++++++++++++++++-
 .../src/main/webapp/app/apps/hdfs/index.js      | 291 ++++++++++++++++++-
 .../app/apps/hdfs/partials/datanodeDetail.html  | 117 ++++++++
 .../app/apps/hdfs/partials/datanodeList.html    |  53 ++++
 .../app/apps/hdfs/partials/namenodeList.html    |  52 ++++
 .../webapp/app/apps/hdfs/partials/overview.html | 106 ++++++-
 .../app/apps/hdfs/widget/availabilityChart.js   | 114 +++++---
 12 files changed, 1276 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
index bd0a278..c74dece 100644
--- 
a/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
+++ 
b/eagle-metric/eagle-hbase-web/src/main/webapp/app/apps/hbase/widgets/availabilityChart.js
@@ -21,12 +21,6 @@
         * `register` without params will load the module which using require
         */
        register(function (hadoopMetricApp) {
-               var COLOR_MAPPING = {
-                       HDFS: 'orange',
-                       HBase: 'yellow',
-                       Yarn: 'green'
-               };
-
                hadoopMetricApp.directive("hadoopMetricWidget", function () {
                        return {
                                restrict: 'AE',
@@ -52,7 +46,7 @@
                                        $scope.type = $attrs.type;
 
                                        // Customize chart color
-                                       $scope.bgColor = 
COLOR_MAPPING[$scope.type];
+                                       $scope.bgColor = "yellow";
 
                                        function countHBaseRole(site, status, 
role, groups, filed, limit) {
                                                var jobCond = {

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/config.json
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/config.json 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/config.json
new file mode 100644
index 0000000..a74e803
--- /dev/null
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/config.json
@@ -0,0 +1,34 @@
+{
+       "namenode": {
+               "heap" : "hadoop.memory.heapmemoryusage.used",
+               "nonheap" : "hadoop.memory.nonheapmemoryusage.used",
+               "fsnamesystemstate" : 
"hadoop.namenode.fsnamesystemstate.capacitytotal",
+               "capacityused" : "hadoop.namenode.dfs.capacityused",
+               "capacityremaining" : "hadoop.namenode.dfs.capacityremaining",
+               "blockstotal" : "hadoop.namenode.dfs.blockstotal",
+               "filestotal" : "hadoop.namenode.dfs.filestotal",
+               "underreplicatedblocks" : 
"hadoop.namenode.dfs.underreplicatedblocks",
+               "missingblocks" : "hadoop.namenode.dfs.missingblocks",
+               "corruptblocks" : "hadoop.namenode.dfs.corruptblocks",
+               "lastcheckpointtime" : "hadoop.namenode.dfs.lastcheckpointtime",
+               "transactionssincelastcheckpoint" : 
"hadoop.namenode.dfs.transactionssincelastcheckpoint",
+               "lastwrittentransactionid" : 
"hadoop.namenode.dfs.lastwrittentransactionid",
+               "snapshottabledirectories" : 
"hadoop.namenode.dfs.snapshottabledirectories",
+               "snapshots" : "hadoop.namenode.dfs.snapshots",
+               "rpcqueuetimeavgtime" : 
"hadoop.namenode.rpc.rpcqueuetimeavgtime",
+               "rpcprocessingtimeavgtime" : 
"hadoop.namenode.rpc.rpcprocessingtimeavgtime",
+               "numopenconnections" : "hadoop.namenode.rpc.numopenconnections",
+               "callqueuelength" : "hadoop.namenode.rpc.callqueuelength"
+       },
+       "datanode": {
+               "nonheap" : "hadoop.memory.nonheapmemoryusage.used",
+               "heap" : "hadoop.memory.heapmemoryusage.used",
+               "capacity" : "hadoop.datanode.fsdatasetstate.capacity",
+               "dfsused" : "hadoop.datanode.fsdatasetstate.dfsused",
+               "xceivercount" : "hadoop.datanode.datanodeinfo.xceivercount",
+               "rpcqueuetimeavgtime" : 
"hadoop.datanode.rpc.rpcqueuetimeavgtime",
+               "rpcprocessingtimeavgtime" : 
"hadoop.datanode.rpc.rpcprocessingtimeavgtime",
+               "numopenconnections" : "hadoop.datanode.rpc.numopenconnections",
+               "callqueuelength" : "hadoop.datanode.rpc.callqueuelength"
+       }
+}

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeDetailCtrl.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeDetailCtrl.js
 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeDetailCtrl.js
new file mode 100644
index 0000000..cdb9ad5
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeDetailCtrl.js
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hdfsMetricApp) {
+               hdfsMetricApp.controller("datanodeDetailCtrl", function ($q, 
$wrapState, $scope, PageConfig, Time, HDFSMETRIC) {
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.hostname = $wrapState.param.hostname;
+                       PageConfig.title = 'Datanode ' + "(" + $scope.hostname 
+ ")";
+                       Time.autoRefresh = false;
+
+                       var sizeoption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, true);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               legend: {
+                                       x: 'center', y: 'bottom'
+                               },
+                               areaStyle: {normal: {}},
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, true);
+                                               }
+                                       }
+                               }]
+                       };
+                       var digitalOption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, false, 0);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, false);
+                                               }
+                                       }
+                               }]
+                       };
+
+                       var gctimeoption = {
+                               legend: {
+                                       x: 'center', y: 'bottom'
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return value / 1000 + ' 
S';
+                                               }
+                                       }
+                               }]
+                       };
+                       $scope.chartList = [
+                               {
+                                       name: "Memory Usage",
+                                       metrics: ["nonheap", "heap"],
+                                       option: sizeoption
+                               },
+                               {
+                                       name: "Fsdatasetstate",
+                                       metrics: ["capacity", "dfsused"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Xceivercount",
+                                       metrics: ["xceivercount"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Rpcqueuetimeavgtime",
+                                       metrics: ["rpcqueuetimeavgtime"],
+                                       option: gctimeoption
+                               },
+                               {
+                                       name: "Rpcprocessingtimeavgtime",
+                                       metrics: ["rpcprocessingtimeavgtime"],
+                                       option: gctimeoption
+                               },
+                               {
+                                       name: "Numopenconnections",
+                                       metrics: ["numopenconnections"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Callqueuelength",
+                                       metrics: ["callqueuelength"],
+                                       option: {}
+                               }
+                       ];
+
+                       $scope.metricList = [];
+                       $.each($scope.chartList, function (i) {
+                               var chart = $scope.chartList[i];
+                               var chartname = chart.name;
+                               $scope.metricList[chartname] = {
+                                       title: chartname,
+                                       series: {},
+                                       option: {},
+                                       loading: true,
+                                       promises: []
+                               };
+                       });
+                       $scope.refresh = function () {
+                               var startTime = Time.startTime();
+                               var endTime = Time.endTime();
+
+                               HDFSMETRIC.getMetricObj().then(function (res) {
+                                       var masterMetricList = res.datanode;
+                                       $.each($scope.chartList, function (i) {
+                                               var chart = $scope.chartList[i];
+                                               var metricList = chart.metrics;
+                                               $.each(metricList, function (j) 
{
+                                                       var metricKey = 
metricList[j];
+                                                       var metricspromies = 
generateHdfsMetric(masterMetricList[metricKey], startTime, endTime, metricKey);
+                                                       var chartname = 
chart.name;
+                                                       
$scope.metricList[chartname].promises.push(metricspromies);
+                                               });
+                                       });
+
+                                       $.each($scope.chartList, function (k) {
+                                               var chart = $scope.chartList[k];
+                                               var chartname = chart.name;
+                                               
$q.all($scope.metricList[chartname].promises).then(function (resp) {
+                                                       var series = [];
+                                                       for (var r = 0; r < 
resp.length; r += 1) {
+                                                               var rs = 
resp[r][1];
+                                                               if (rs.length > 
0) {
+                                                                       
series.push(rs);
+                                                               }
+                                                       }
+                                                       
$scope.metricList[chartname] = mergeSeries(chartname, series, chart.metrics, 
chart.option);
+                                               });
+                                       });
+                               });
+
+                               
HDFSMETRIC.getStatusByRoleAndHost("HdfsServiceInstance",$scope.hostname, 
"datanode", $scope.site)._promise.then(function (res) {
+                                       $scope.datanodestatus = res;
+                               });
+                       };
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
+
+
+                       function generateHdfsMetric(name, startTime, endTime, 
flag) {
+                               var interval = Time.diffInterval(startTime, 
endTime);
+                               var intervalMin = interval / 1000 / 60;
+                               var trendStartTime = Time.align(startTime, 
interval);
+                               var trendEndTime = Time.align(endTime, 
interval);
+
+                               var condition = {
+                                       site: $scope.site,
+                                       component: "regionserver",
+                                       host: $scope.hostname
+                               };
+                               return 
HDFSMETRIC.aggMetricsToEntities(HDFSMETRIC.hadoopMetricsAggregation(condition, 
name, ["site"], "avg(value)", intervalMin, trendStartTime, trendEndTime), flag)
+                                       ._promise.then(function (list) {
+                                               var metricFlag = $.map(list, 
function (metrics) {
+                                                       return metrics[0].flag;
+                                               });
+                                               return [metricFlag, list];
+                                       });
+                       }
+
+                       function mergeSeries(title, metrics, linename, option) {
+                               var series = [];
+                               $.each(metrics, function (i, metricMap) {
+                                       $.map(metricMap, function (metric) {
+                                               if (typeof metric !== 
'undefined') {
+                                                       
series.push(HDFSMETRIC.metricsToSeries(linename[i], metric, option));
+                                               }
+                                       });
+                               });
+                               return {
+                                       title: title,
+                                       series: series,
+                                       option: option || {},
+                                       loading: false
+                               };
+                       }
+               });
+       });
+})
+();

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/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
new file mode 100644
index 0000000..aee0536
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/datanodeListCtrl.js
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hdfsMetricApp) {
+
+               hdfsMetricApp.controller("datanodeListCtrl", function 
($wrapState, $scope, PageConfig, HDFSMETRIC) {
+
+                       // Initialization
+                       PageConfig.title = "HDFS Datanode";
+                       $scope.tableScope = {};
+                       $scope.live = HDFSMETRIC.STATUS_LIVE;
+                       $scope.dead = HDFSMETRIC.STATUS_DEAD;
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.searchPathList = [["tags", "hostname"], ["tags", 
"rack"], ["tags", "site"], ["status"]];
+                       $scope.datanodeList = 
HDFSMETRIC.getListByRoleName("HdfsServiceInstance", "datanode", $scope.site);
+
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/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
new file mode 100644
index 0000000..3e4ea41
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/namenodeListCtrl.js
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+       /**
+        * `register` without params will load the module which using require
+        */
+       register(function (hdfsMetricApp) {
+
+               hdfsMetricApp.controller("namenodeListCtrl", function 
($wrapState, $scope, PageConfig, HDFSMETRIC) {
+
+                       // Initialization
+                       PageConfig.title = "HDFS Namenode List";
+                       $scope.tableScope = {};
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.searchPathList = [["tags", "hostname"], ["tags", 
"rack"], ["tags", "site"], ["status"]];
+                       $scope.namenodeList = 
HDFSMETRIC.getListByRoleName("HdfsServiceInstance", "namenode", $scope.site);
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
index b8d57a7..d77986a 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/ctrl/overview.js
@@ -21,9 +21,268 @@
         * `register` without params will load the module which using require
         */
        register(function (hdfsMetricApp) {
-               hdfsMetricApp.controller("overviewCtrl", function (PageConfig) {
-                       PageConfig.title = 'Hdfs';
+               hdfsMetricApp.controller("overviewCtrl", function ($q, 
$wrapState, $scope, PageConfig, HDFSMETRIC, Time) {
+                       PageConfig.title = 'HDFS';
 
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+
+                       var namenodeInfo = 
HDFSMETRIC.getListByRoleName("HdfsServiceInstance", "namenode", $scope.site);
+
+                       $scope.switchNamenode = function (namenode) {
+                               $scope.metricList = [];
+                               $.each($scope.chartList, function (i) {
+                                       var chart = $scope.chartList[i];
+                                       var chartname = chart.name;
+                                       $scope.metricList[chartname] = {
+                                               title: chartname,
+                                               series: {},
+                                               option: {},
+                                               loading: true,
+                                               promises: []
+                                       };
+                               });
+                               $scope.namenode = namenode;
+                               $scope.refresh();
+                       };
+
+                       var storageOption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, true, 0);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, true);
+                                               }
+                                       }
+                               }]
+                       };
+
+                       var digitalOption = {
+                               animation: false,
+                               tooltip: {
+                                       formatter: function (points) {
+                                               return points[0].name + "<br/>" 
+
+                                                       $.map(points, function 
(point) {
+                                                               return '<span 
style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:'
 + point.color + '"></span> ' +
+                                                                       
point.seriesName + ": " +
+                                                                       
common.number.abbr(point.value, false, 0);
+                                                       
}).reverse().join("<br/>");
+                                       }
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return 
common.number.abbr(value, false);
+                                               }
+                                       }
+                               }]
+                       };
+                       var startTime = Time.startTime();
+                       var endTime = Time.endTime();
+                       var interval = Time.diffInterval(startTime, endTime);
+                       var intervalMin = interval / 1000 / 60;
+                       var trendStartTime = Time.align(startTime, interval);
+                       var trendEndTime = Time.align(endTime, interval);
+                       $scope.site = $wrapState.param.siteId;
+                       function generateHdfsMetric(name, flag) {
+                               var result = cache[name] || 
namenodeInfo._promise.then(function (res) {
+                                               $scope.activeNamenodeList = res;
+                                               $scope.type = 
$wrapState.param.hostname || $scope.namenode || res[0].tags.hostname;
+                                               var hostname = $scope.namenode 
|| res[0].tags.hostname;
+                                               var jobCond = {
+                                                       site: $scope.site,
+                                                       component: "namenode",
+                                                       host: hostname
+                                               };
+                                               return 
HDFSMETRIC.aggMetricsToEntities(HDFSMETRIC.hadoopMetricsAggregation(jobCond, 
name, ["site"], "avg(value)", intervalMin, trendStartTime, trendEndTime), flag)
+                                                       ._promise.then(function 
(list) {
+                                                               var metricFlag 
= $.map(list, function (metrics) {
+                                                                       return 
metrics[0].flag;
+                                                               });
+                                                               return 
[metricFlag, list];
+                                                       });
+                                       });
+                               return result;
+                       }
+
+                       function sumMetrics(site, role, groups, filed, limit) {
+                               var jobCond = {
+                                       site: site,
+                                       role: role
+                               };
+                               return 
HDFSMETRIC.aggHadoopInstance("HdfsServiceInstance", jobCond, groups, filed, 
limit);
+                       }
+
+                       $scope.chartList = [
+                               {
+                                       name: "MemoryUsage",
+                                       metrics: ["nonheap", "heap"],
+                                       linename: ["nonheap", "heap"],
+                                       option: storageOption
+                               },
+                               {
+                                       name: "DFSCapacity",
+                                       metrics: ["fsnamesystemstate", 
"capacityused", "capacityremaining"],
+                                       linename: ["total", "used", 
"remainning"],
+                                       option: storageOption
+                               },
+                               {
+                                       name: "Blocks",
+                                       metrics: ["blockstotal", 
"missingblocks", "corruptblocks"],
+                                       linename: ["blockstotal", 
"missingblocks", "corruptblocks"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "Filestotal",
+                                       metrics: ["filestotal"],
+                                       linename: ["filestotal"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "Underreplicatedblocks",
+                                       metrics: ["underreplicatedblocks"],
+                                       linename: ["underreplicatedblocks"],
+                                       option: {}
+                               },
+                               {
+                                       name: "LastCheckpointTime",
+                                       metrics: ["lastcheckpointtime"],
+                                       linename: ["lastcheckpointtime"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "TransactionsSinceLastCheckpoint",
+                                       metrics: 
["transactionssincelastcheckpoint"],
+                                       linename: 
["transactionssincelastcheckpoint"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "LastWrittenTransactionId",
+                                       metrics: ["lastwrittentransactionid"],
+                                       linename: ["lastwrittentransactionid"],
+                                       option: digitalOption
+                               },
+                               {
+                                       name: "SnapshottableDirectories",
+                                       metrics: ["snapshottabledirectories"],
+                                       linename: ["snapshottabledirectories"],
+                                       option: {}
+                               },
+                               {
+                                       name: "Snapshots",
+                                       metrics: ["snapshots"],
+                                       linename: ["snapshots"],
+                                       option: {}
+                               },
+                               {
+                                       name: "RpcAvgTime",
+                                       metrics: ["rpcqueuetimeavgtime", 
"rpcprocessingtimeavgtime"],
+                                       linename: ["queuetime", 
"processingtime"],
+                                       option: {}
+                               },
+                               {
+                                       name: "NumOpenConnections",
+                                       metrics: ["numopenconnections"],
+                                       linename: ["numopenconnections"],
+                                       option: {}
+                               },
+                               {
+                                       name: "CallQueueLength",
+                                       metrics: ["callqueuelength"],
+                                       linename: ["callqueuelength"],
+                                       option: {}
+                               }
+                       ];
+
+                       $scope.metricList = [];
+                       $.each($scope.chartList, function (i) {
+                               var chart = $scope.chartList[i];
+                               var chartname = chart.name;
+                               $scope.metricList[chartname] = {
+                                       title: chartname,
+                                       series: {},
+                                       option: {},
+                                       loading: true,
+                                       promises: []
+                               };
+                       });
+
+                       $scope.refresh = function () {
+                               HDFSMETRIC.getMetricObj().then(function(res) {
+                                       var namenodeMetricList = res.namenode;
+                                       $.each($scope.chartList, function (i) {
+                                               var chart = $scope.chartList[i];
+                                               var metricList = chart.metrics;
+                                               $.each(metricList, function (j) 
{
+                                                       var metricKey = 
metricList[j];
+                                                       var metricpromise = 
generateHdfsMetric(namenodeMetricList[metricKey], metricKey);
+                                                       var chartname = 
chart.name;
+                                                       
$scope.metricList[chartname].promises.push(metricpromise);
+                                               });
+                                       });
+                                       $.each($scope.chartList, function (k) {
+                                               var chart = $scope.chartList[k];
+                                               var chartname = chart.name;
+                                               
$q.all($scope.metricList[chartname].promises).then(function (resp) {
+                                                       var series = [];
+                                                       for(var r=0; r < 
resp.length; r+=1) {
+                                                               var rs = 
resp[r][1];
+                                                               if(rs.length > 
0) {
+                                                                       
series.push(rs);
+                                                               }
+                                                       }
+                                                       
$scope.metricList[chartname] = HDFSMETRIC.mergeMetricToOneSeries(chartname, 
series, chart.linename, chart.option);
+                                               });
+                                       });
+                               });
+
+                               
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", $scope.site, "active", 
"namenode", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.namenodeactivenum = 
data.value[0];
+                                       });
+                               });
+                               
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", $scope.site, "standby", 
"namenode", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.namenodestandbynum = 
data.value[0];
+                                       });
+                               });
+                               
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", $scope.site, "live", 
"datanode", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.datanodehealtynum = 
data.value[0];
+                                       });
+                               });
+                               
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", $scope.site, "dead", 
"datanode", ["site"], "count")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.datanodeunhealtynum = 
data.value[0];
+                                       });
+                               });
+                               sumMetrics($scope.site, "datanode", ["site"], 
"sum(configuredCapacityTB)")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.capacityNum = 
data.value[0];
+                                       });
+                               });
+                               sumMetrics($scope.site, "datanode", ["site"], 
"sum(usedCapacityTB)")._promise.then(function (res) {
+                                       $.map(res, function (data) {
+                                               $scope.usedCapacityNum = 
data.value[0];
+                                       });
+                               });
+                       };
+
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
                });
        });
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
----------------------------------------------------------------------
diff --git a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
index 48b3feb..a4d6576 100644
--- a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
+++ b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/index.js
@@ -23,11 +23,34 @@
        var hdfsMetricApp = register(['ngRoute', 'ngAnimate', 'ui.router', 
'eagle.service']);
 
        hdfsMetricApp.route("HdfsMetric", {
-               url: "/hadoopService/hdfs",
+               url: "/hadoopService/hdfs?startTime&endTime",
                site: true,
                templateUrl: "partials/overview.html",
                controller: "overviewCtrl",
                resolve: {time: true}
+       }).route("datanodeDetail", {
+               url: "/hadoopService/hdfs/datanode/:hostname",
+               site: true,
+               templateUrl: "partials/datanodeDetail.html",
+               controller: "datanodeDetailCtrl",
+               resolve: {time: true}
+       }).route("datanodeList", {
+               url: "/hadoopService/hdfs/datanodeList",
+               site: true,
+               templateUrl: "partials/datanodeList.html",
+               controller: "datanodeListCtrl"
+       }).route("namenodeList", {
+               url: "/hadoopService/hdfs/namenodeList",
+               site: true,
+               templateUrl: "partials/namenodeList.html",
+               controller: "namenodeListCtrl"
+       }).route("namenodeDetail", {
+               url: "/hadoopService/hdfs:hostname?startTime&endTime",
+               site: true,
+               reloadOnSearch: false,
+               templateUrl: "partials/overview.html",
+               controller: "overviewCtrl",
+               resolve: {time: true}
        });
 
        hdfsMetricApp.portal({
@@ -36,7 +59,273 @@
                ]
        }, true);
 
+       hdfsMetricApp.service("HDFSMETRIC", function ($q, $http, Time, Site, 
Application) {
+               var HDFSMETRIC = window._HDFSMETRIC = {};
+               HDFSMETRIC.STATUS_LIVE = "live";
+               HDFSMETRIC.STATUS_DEAD = "dead";
+               HDFSMETRIC.QUERY_HBASE_HDFSMETRICS = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]{*}&metricName=${metric}&pageSize=${limit}';
+
+               HDFSMETRIC.QUERY_HADOOP_INSTANCE = 
'${baseURL}/rest/entities?query=${service}[${condition}]{*}&pageSize=${limit}';
+               HDFSMETRIC.QUERY_HADOOP_INSTANCE_AGG = 
"${baseURL}/rest/entities?query=${service}[${condition}]<${groups}>{${field}}&pageSize=${limit}";
+               HDFSMETRIC.QUERY_HADOOP_HDFSMETRICS_INTERVAL = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]<${groups}>{${field}}${order}${top}&metricName=${metric}&pageSize=${limit}&startTime=${startTime}&endTime=${endTime}&intervalmin=${intervalMin}&timeSeries=true';
+
+               /**
+                * Fetch query content with current site application 
configuration
+                * @param {string} queryName
+                */
+               var getQuery = HDFSMETRIC.getQuery = function (queryName, 
siteId) {
+                       var baseURL;
+                       siteId = siteId || Site.current().siteId;
+                       var app = Application.find("HDFS_METRIC_WEB_APP", 
siteId)[0];
+                       var host = app.configuration["service.host"];
+                       var port = app.configuration["service.port"];
+
+                       if (!host && !port) {
+                               baseURL = "";
+                       } else {
+                               if (host === "localhost" || !host) {
+                                       host = location.hostname;
+                               }
+                               if (!port) {
+                                       port = location.port;
+                               }
+                               baseURL = "http://"; + host + ":" + port;
+                       }
+
+                       return common.template(HDFSMETRIC["QUERY_" + 
queryName], {baseURL: baseURL});
+               };
+
+               function wrapList(promise) {
+                       var _list = [];
+                       _list._done = false;
+                       _list._promise = promise.then(
+                               /**
+                                * @param {{}} res
+                                * @param {{}} res.data
+                                * @param {{}} res.data.obj
+                                */
+                               function (res) {
+                                       _list.splice(0);
+                                       Array.prototype.push.apply(_list, 
res.data.obj);
+                                       _list._done = true;
+                                       return _list;
+                               });
+                       return _list;
+               }
+
+               function toFields(fields) {
+                       return (fields || []).length > 0 ? $.map(fields, 
function (field) {
+                               return "@" + field;
+                       }).join(",") : "*";
+               }
+
+               HDFSMETRIC.metricsToSeries = function (name, metrics, option, 
rawData) {
+                       if (arguments.length === 4 && typeof rawData === 
"object") {
+                               option = rawData;
+                               rawData = false;
+                       }
+
+                       var data = $.map(metrics, function (metric) {
+                               return rawData ? metric.value[0] : {
+                                       x: metric.timestamp,
+                                       y: metric.value[0]
+                               };
+                       });
+                       return $.extend({
+                               name: name,
+                               showSymbol: false,
+                               type: "line",
+                               data: data
+                       }, option || {});
+               };
+
+               HDFSMETRIC.get = function (url, params) {
+                       return $http({
+                               url: url,
+                               method: "GET",
+                               params: params
+                       });
+               };
+
+               HDFSMETRIC.condition = function (condition) {
+                       return $.map(condition, function (value, key) {
+                               return "@" + key + '="' + value + '"';
+                       }).join(" AND ");
+               };
+
+               HDFSMETRIC.aggHadoopInstance = function (service, condition, 
groups, field, limit) {
+                       var fields = field.split(/\s*,\s*/);
+                       var fieldStr = $.map(fields, function (field, index) {
+                               var matches = field.match(/^([^\s]*)(\s+.*)?$/);
+                               if (matches[2]) {
+                                       orderId = index;
+                               }
+                               return matches[1];
+                       }).join(", ");
+                       var config = {
+                               service: service,
+                               condition: HDFSMETRIC.condition(condition),
+                               groups: toFields(groups),
+                               field: fieldStr,
+                               limit: limit || 10000
+                       };
+                       var metrics_url = 
common.template(getQuery("HADOOP_INSTANCE_AGG"), config);
+                       return wrapList(HDFSMETRIC.get(metrics_url));
+               };
+
+               HDFSMETRIC.countHadoopRole = function(service, site, status, 
role, groups, filed, limit) {
+                       var jobCond = {
+                               site: site,
+                               status: status,
+                               role: role
+                       };
+                       return HDFSMETRIC.aggHadoopInstance(service, jobCond, 
groups, filed, limit);
+               };
+
+               HDFSMETRIC.hadoopMetricsAggregation = function (condition, 
metric, groups, field, intervalMin, startTime, endTime, top, limit) {
+                       var fields = field.split(/\s*,\s*/);
+                       var orderId = -1;
+                       var fieldStr = $.map(fields, function (field, index) {
+                               var matches = field.match(/^([^\s]*)(\s+.*)?$/);
+                               if (matches[2]) {
+                                       orderId = index;
+                               }
+                               return matches[1];
+                       }).join(", ");
+
+
+                       var config = {
+                               condition: HDFSMETRIC.condition(condition),
+                               startTime: Time.format(startTime),
+                               endTime: Time.format(endTime),
+                               metric: metric,
+                               groups: toFields(groups),
+                               field: fieldStr,
+                               order: orderId === -1 ? "" : ".{" + 
fields[orderId] + "}",
+                               top: top ? "&top=" + top : "",
+                               intervalMin: intervalMin,
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HADOOP_HDFSMETRICS_INTERVAL"), config);
+                       var _list = wrapList(HDFSMETRIC.get(metrics_url));
+                       _list._aggInfo = {
+                               groups: groups,
+                               startTime: Time(startTime).valueOf(),
+                               interval: intervalMin * 60 * 1000
+                       };
+                       _list._promise.then(function () {
+                               _list.reverse();
+                       });
+                       return _list;
+               };
+
+               HDFSMETRIC.aggMetricsToEntities = function (list, param, 
flatten) {
+                       var _list = [];
+                       _list.done = false;
+                       _list._promise = list._promise.then(function () {
+                               var _startTime = list._aggInfo.startTime;
+                               var _interval = list._aggInfo.interval;
+
+                               $.each(list, function (i, obj) {
+                                       var tags = {};
+                                       $.each(list._aggInfo.groups, function 
(j, group) {
+                                               tags[group] = obj.key[j];
+                                       });
+
+                                       var _subList = $.map(obj.value[0], 
function (value, index) {
+                                               return {
+                                                       timestamp: _startTime + 
index * _interval,
+                                                       value: [value],
+                                                       tags: tags,
+                                                       flag: param
+                                               };
+                                       });
+
+                                       if (flatten) {
+                                               _list.push.apply(_list, 
_subList);
+                                       } else {
+                                               _list.push(_subList);
+                                       }
+                               });
+                               _list.done = true;
+                               return _list;
+                       });
+                       return _list;
+               };
+
+               HDFSMETRIC.hadoopHostStatus = function (service, condition, 
limit) {
+                       var config = {
+                               service: service,
+                               condition: HDFSMETRIC.condition(condition),
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HADOOP_INSTANCE"), config);
+                       return wrapList(HDFSMETRIC.get(metrics_url));
+               };
+
+               HDFSMETRIC.getHadoopHostByStatusAndRole = function (service, 
siteId, status,role, limit) {
+                       var condition = {
+                               site: siteId,
+                               role: role,
+                               status: status
+                       };
+                       return HDFSMETRIC.hadoopHostStatus(service, condition, 
limit);
+               };
+
+               HDFSMETRIC.getStatusByRoleAndHost = function (service, 
hostname, role, siteid) {
+                       var hoststateinfo;
+                       var condition = {
+                               site: siteid,
+                               role: role,
+                               hostname: hostname
+                       };
+                       hoststateinfo = HDFSMETRIC.hadoopHostStatus(service, 
condition);
+                       return hoststateinfo;
+               };
+
+               HDFSMETRIC.getListByRoleName = function (service, role, siteid) 
{
+                       var hoststateinfos;
+                       var condition = {
+                               site: siteid,
+                               role: role
+                       };
+                       hoststateinfos = HDFSMETRIC.hadoopHostStatus(service, 
condition);
+                       return hoststateinfos;
+               };
+
+               HDFSMETRIC.getMetricObj = function () {
+                       var deferred = $q.defer();
+                       $http.get("apps/hdfs/config.json").success(function 
(resp) {
+                               deferred.resolve(resp);
+                       });
+                       return deferred.promise;
+               };
+
+               HDFSMETRIC.mergeMetricToOneSeries = function (metricTitle, 
metrics, legendName, dataOption, option) {
+                       var series = [];
+
+                       $.each(metrics, function (i, metricMap) {
+                               if (typeof metricMap !== 'undefined') {
+                                       
series.push(HDFSMETRIC.metricsToSeries(legendName[i], metricMap[0], option));
+                               }
+                       });
+                       return {
+                               title: metricTitle,
+                               series: series,
+                               option: dataOption || {},
+                               loading: false
+                       };
+               };
+
+               return HDFSMETRIC;
+       });
+
     hdfsMetricApp.requireCSS("style/index.css");
     hdfsMetricApp.require("widget/availabilityChart.js");
        hdfsMetricApp.require("ctrl/overview.js");
+       hdfsMetricApp.require("ctrl/namenodeListCtrl.js");
+       hdfsMetricApp.require("ctrl/datanodeListCtrl.js");
+       hdfsMetricApp.require("ctrl/datanodeDetailCtrl.js");
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeDetail.html
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeDetail.html
 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeDetail.html
new file mode 100644
index 0000000..7a91cdb
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeDetail.html
@@ -0,0 +1,117 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "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
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  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">
+               <span class="fa fa-television"></span>
+               <h3 class="box-title">
+                       Summary
+               </h3>
+       </div>
+       <div class="box-body">
+               <table class="table table-striped">
+                       <tbody ng-if="(datanodestatus || []).length !== 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break">
+                                       <span 
ng-if="datanodestatus[0].status==='live'" class="label 
label-success">Healthy</span>
+                                       <span 
ng-if="datanodestatus[0].status!=='live'" class="label 
label-danger">UnHealthy</span>
+                               </td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td 
class="text-break">{{datanodestatus[0].tags.rack}}</td>
+                       </tr>
+                       <tr>
+                               <th>ConfiguredCapacityTB</th>
+                               <td 
class="text-break">{{common.number.format(common.number.parse(datanodestatus[0].configuredCapacityTB),
 0)}} TB</td>
+                       </tr>
+                       <tr>
+                               <th>UsedCapacityTB</th>
+                               <td 
class="text-break">{{common.number.format(common.number.parse(datanodestatus[0].usedCapacityTB),
 0)}} TB</td>
+                       </tr>
+                       <tr>
+                               <th>NumBlocks</th>
+                               <td 
class="text-break">{{common.number.format(common.number.parse(datanodestatus[0].numBlocks),
 0)}}</td>
+                       </tr>
+                       <tr>
+                               <th>NumFailedVolumes</th>
+                               <td 
class="text-break">{{common.number.format(common.number.parse(datanodestatus[0].numFailedVolumes),
 0)}}</td>
+                       </tr>
+                       </tbody>
+                       <tbody ng-if="datanodestatus.length === 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       <tr>
+                               <th>ConfiguredCapacityTB</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       <tr>
+                               <th>UsedCapacityTB</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumBlocks</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumFailedVolumes</th>
+                               <td class="text-break"><span class="label 
label-danger">N/A</span></td>
+                       </tr>
+                       </tbody>
+               </table>
+       </div>
+</div>
+
+<div class="box box-primary">
+       <div class="box-header with-border">
+               <span class="fa fa-line-chart"></span>
+               <h3 class="box-title">
+                       Metrics
+               </h3>
+       </div>
+       <div class="box-body no-padding">
+               <div class="row border-split">
+                       <div class="col-sm-6 hadoopMetric-col-md-6 col-lg-6" 
ng-repeat="chart in chartList track by $index">
+                               <div class="hadoopMetric-chart">
+                                       
<h3>{{metricList[chart.name].title}}</h3>
+                                       <div 
ng-show="metricList[chart.name].loading" 
class="hadoopMetric-chart-container"></div>
+                                       <div 
ng-show="metricList[chart.name].loading" class="overlay-wrapper">
+                                               <div class="overlay">
+                                                       <i class="fa fa-refresh 
fa-spin"></i>
+                                               </div>
+                                       </div>
+                                       <div 
ng-show="metricList[chart.name].series.length" chart 
class="hadoopMetric-chart-container"
+                                                
series="metricList[chart.name].series"
+                                                
option="metricList[chart.name].option"></div>
+                                       <div 
ng-show="!metricList[chart.name].series.length && 
!metricList[chart.name].loading" class="hadoopMetric-chart-container">
+                                               <div 
class="hadoopMetric-no-chart-data">
+                                                       <span class="fa 
fa-question-circle"></span><span> NO DATA</span>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/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
new file mode 100644
index 0000000..0a31b9e
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/datanodeList.html
@@ -0,0 +1,53 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "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
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  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">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 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>

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/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
new file mode 100644
index 0000000..d10aa0b
--- /dev/null
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/partials/namenodeList.html
@@ -0,0 +1,52 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "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
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  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>
+       </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/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 678b221..328b869 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
@@ -6,7 +6,9 @@
   to you under the Apache License, Version 2.0 (the
   "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
+
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -14,4 +16,106 @@
   limitations under the License.
   -->
 
-HDFS Page
+<div class="box box-primary">
+    <div class="box-header with-border">
+        <span class="fa fa-television"></span>
+        <h3 class="box-title">
+            HDFS Namenode Service Summary Information
+        </h3>
+    </div>
+    <div class="box-body">
+        <table class="table table-striped hadoopMetric-table">
+            <tr>
+                <td width="5%">
+                    <a ui-sref="namenodeList({siteId: site})" target="_blank">
+                        <span 
ng-show="namenodeactivenum">{{namenodeactivenum}}</span></a>
+                    <span ng-show="!namenodeactivenum">N/A</span>
+                </td>
+                <th width="30%">Active Namenode</th>
+                <td>
+                    <span 
ng-show="capacityNum">{{common.number.format(capacityNum, 0)}} TB</span>
+                    <span ng-show="!capacityNum">N/A</span>
+                    Capacity <span 
ng-show="usedCapacityNum">{{common.number.format(usedCapacityNum, 0)}} TB</span>
+                    <span ng-show="!usedCapacityNum">N/A</span> usedCapacity
+
+                </td>
+                <th width="30%">
+                </th>
+            </tr>
+            <tr>
+                <td>
+                    <a ui-sref="namenodeList({siteId: site})" target="_blank">
+                        <span 
ng-show="namenodestandbynum">{{namenodestandbynum}}</span></a>
+                    <span ng-show="!namenodestandbynum">N/A</span>
+                </td>
+                <th>Backup Namenode</th>
+            </tr>
+            <tr>
+                <td>
+                    <a ui-sref="datanodeList({siteId: site})">
+                        <span ng-show="datanodehealtynum || 
datanodeunhealtynum">{{datanodehealtynum+datanodeunhealtynum}}</span></a>
+                    <span ng-show="!datanodehealtynum && 
!datanodeunhealtynum">N/A</span>
+                </td>
+                <th>Datanodes:
+                    <span 
ng-show="datanodehealtynum">{{datanodehealtynum}}</span>
+                    <span ng-show="!datanodehealtynum">N/A</span>
+                    <span
+                            class="label label-success">Good Health</span> /
+                    <a ui-sref="datanodeList({siteId: site})">
+                        <span 
ng-show="datanodeunhealtynum">{{datanodeunhealtynum}}</span></a>
+                    <span ng-show="!datanodeunhealtynum">0</span>
+                    <span class="label label-danger">Bad Health</span>
+                </th>
+                <td></td>
+                <th></th>
+            </tr>
+        </table>
+    </div>
+</div>
+
+<div class="box box-primary">
+    <div class="box-header with-border">
+        <span class="fa fa-line-chart"></span>
+        <h3 class="box-title">
+            Metrics
+        </h3>
+    </div>
+
+    <div class="nav-tabs-custom">
+        <ul class="nav nav-tabs">
+            <li ng-class="{active: type===namenode.tags.hostname}"
+                ng-repeat="namenode in activeNamenodeList track by $index">
+                <a ng-click="switchNamenode(namenode.tags.hostname)" 
data-toggle="tab" 
aria-expanded="true">{{namenode.tags.hostname}}({{namenode.status}})</a>
+            </li>
+        </ul>
+        <div class="tab-content">
+            <div class="tab-pane active" id="tab_1">
+                <div class="box-body no-padding">
+                    <div class="row border-split">
+                        <div class="col-sm-6 col-md-4 col-lg-6" 
ng-repeat="chart in chartList track by $index">
+                            <div class="hadoopMetric-chart">
+                                <h3>{{metricList[chart.name].title}}</h3>
+                                <div ng-show="metricList[chart.name].loading"
+                                     class="fa fa-refresh fa-spin 
no-animate"></div>
+                                <div 
ng-show="metricList[chart.name].series.length" chart
+                                     class="hadoopMetric-chart-container"
+                                     series="metricList[chart.name].series"
+                                     
option="metricList[chart.name].option"></div>
+                                <div 
ng-show="!metricList[chart.name].series.length && 
!metricList[chart.name].loading"
+                                     class="hadoopMetric-chart-container">
+                                    <div 
class="hadoopMetric-chart-container-withborder">
+                                        <div 
class="hadoopMetric-no-chart-data">
+                                            <span class="fa 
fa-question-circle"></span><span> NO DATA</span>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/610b9f2e/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
----------------------------------------------------------------------
diff --git 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
index fbfc73d..6653438 100644
--- 
a/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
+++ 
b/eagle-metric/eagle-hdfs-web/src/main/webapp/app/apps/hdfs/widget/availabilityChart.js
@@ -21,67 +21,91 @@
         * `register` without params will load the module which using require
         */
        register(function (hdfsMetricApp) {
-               var COLOR_MAPPING = {
-                       HDFS: 'orange',
-                       HBase: 'yellow',
-                       Yarn: 'green',
-               };
-
-               var widgetChartOption = {
-                       color: ['#FFFFFF'],
-                       grid: {
-                               top: 0,
-                               right: 0,
-                               bottom: 0,
-                               left: 0,
-                               containLabel: false,
-                       },
-                       xAxis: {
-                               axisLine: {show: false},
-                               axisLabel: {show: false},
-                       },
-                       yAxis: [{
-                               axisLine: {show: false},
-                               axisLabel: {show: false},
-                               axisTick: {show: false},
-                               splitLine: {show: false},
-                       }],
-               };
-
                hdfsMetricApp.directive("hdfsMetricWidget", function () {
                        return {
                                restrict: 'AE',
-                               controller: function($scope, $attrs) {
+                               controller: function ($scope, $attrs, 
HDFSMETRIC, Application, $interval) {
                                        // Get site
                                        var site = $scope.site;
+                                       var refreshInterval;
 
+                                       if(!site) {
+                                               $scope.list = 
$.map(Application.find("HDFS_METRIC_WEB_APP"), function (app) {
+                                                       return {
+                                                               siteId: 
app.site.siteId,
+                                                               siteName: 
app.site.siteName || app.site.siteId
+                                                       };
+                                               });
+                                       } else {
+                                               $scope.list = [{
+                                                       siteId: site.siteId,
+                                                       siteName: site.siteName 
|| site.siteId
+                                               }];
+                                       }
                                        // Get type
                                        $scope.type = $attrs.type;
 
                                        // Customize chart color
-                                       $scope.bgColor = 
COLOR_MAPPING[$scope.type];
+                                       $scope.bgColor = "orange";
 
-                                       $scope.chartOption = widgetChartOption;
+                                       function refresh() {
+                                               $.each($scope.list, function 
(i, site) {
 
-                                       // Mock fetch data
-                                       var now = +new Date();
-                                       var data = [];
-                                       for(var j = 0 ; j < 30 ; j += 1) {
-                                               data.push({x: now + j * 1000 * 
60, y: Math.random() * 100});
+                                                       
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", site.siteId, "active", 
"namenode", ["site"], "count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.namenodeactivenum = data.value[0];
+                                                               });
+                                                       });
+                                                       
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", site.siteId, "standby", 
"namenode", ["site"], "count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.namenodestandbynum = data.value[0];
+                                                               });
+                                                       });
+                                                       
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", site.siteId, "live", 
"datanode", ["site"], "count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.datanodehealtynum = data.value[0];
+                                                               });
+                                                       });
+                                                       
HDFSMETRIC.countHadoopRole("HdfsServiceInstance", site.siteId, "dead", 
"datanode", ["site"], "count")._promise.then(function (res) {
+                                                               $.map(res, 
function (data) {
+                                                                       
$scope.datanodeunhealtynum = data.value[0];
+                                                               });
+                                                       });
+                                               });
                                        }
-                                       $scope.series = [{
-                                               name: '',
-                                               type: 'line',
-                                               data: data,
-                                               showSymbol: false,
-                                       }];
 
-                                       // Ref: jpm widget if need keep refresh 
the widget
+                                       refresh();
+                                       refreshInterval = $interval(refresh, 30 
* 1000);
+
+                                       $scope.$on('$destroy', function () {
+                                               
$interval.cancel(refreshInterval);
+                                       });
                                },
                                template:
-                               '<div class="hadoopMetric-widget 
bg-{{bgColor}}">' +
-                                       '<h3>{{type}}</h3>' +
-                                       '<div chart 
class="hadoopMetric-chart-container" series="series" 
option="chartOption"></div>' +
+                               '<div class="small-box hadoopMetric-widget 
bg-{{bgColor}}">' +
+                               '<div class="inner">' +
+                               '<h3>{{type}}</h3>' +
+                               '<div ng-show="namenodeactivenum" 
class="hadoopMetric-widget-detail">' +
+                               '<a ui-sref="namenodeList({siteId: 
site.siteId})">' +
+                               
'<span>{{namenodeactivenum+namenodestandbynum}}</span> Namenodes (' +
+                               '<span 
ng-show="namenodeactivenum">{{namenodeactivenum}}</span><span 
ng-show="!namenodeactivenum">0</span> Active / ' +
+                               '<span 
ng-show="namenodestandbynum">{{namenodestandbynum}}</span><span 
ng-show="!namenodestandbynum">0</span> Standby)' +
+                               '</a>' +
+                               '</div>' +
+                               '<div ng-show="!namenodeactivenum" 
class="hadoopMetric-widget-detail">' +
+                               '<span class="fa 
fa-question-circle"></span><span> NO DATA</span>' +
+                               '</div>' +
+                               '<div ng-show="namenodeactivenum" 
class="hadoopMetric-widget-detail">' +
+                               '<a ui-sref="datanodeList({siteId: 
site.siteId})">' +
+                               
'<span>{{datanodehealtynum+datanodeunhealtynum}}</span> Datanodes (' +
+                               '<span 
ng-show="datanodehealtynum">{{datanodehealtynum}}</span><span 
ng-show="!datanodehealtynum">0</span> Healthy / ' +
+                               '<span 
ng-show="datanodeunhealtynum">{{datanodeunhealtynum}}</span><span 
ng-show="!datanodeunhealtynum">0</span> Unhealthy)' +
+                               '</a>' +
+                               '</div>' +
+                               '</div>' +
+                               '<div class="icon">' +
+                               '<i class="fa fa-taxi"></i>' +
+                               '</div>' +
                                '</div>',
                                replace: true
                        };

Reply via email to