Repository: eagle
Updated Branches:
  refs/heads/master d2fee6e6f -> 257a3517b


[EAGLE-845] JMX Dashboard

EAGLE-845 JMX Dashboard
- Add HBase master metric dashboard.
- Add HBase RegionServer metric dashboard.
- Integrate hbase metric to basic panel.

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

Author: chitin <[email protected]>
Author: r7raul1984 <[email protected]>

Closes #753 from chitin/hbase-jmx-metric.


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

Branch: refs/heads/master
Commit: 257a3517bf0b191dfe931c21232810f65cfc5a63
Parents: d2fee6e
Author: chitin <[email protected]>
Authored: Fri Jan 6 11:25:44 2017 +0800
Committer: zombieJ <[email protected]>
Committed: Fri Jan 6 11:25:44 2017 +0800

----------------------------------------------------------------------
 ...le.metric.HadoopMetricMonitorAppProdiver.xml |  16 ++
 .../webapp/app/apps/hadoop_metric/config.json   |  68 +++++
 .../app/apps/hadoop_metric/ctrls/overview.js    | 172 +++++++++---
 .../hadoop_metric/ctrls/regionDetailCtrl.js     | 164 ++++++++++++
 .../apps/hadoop_metric/ctrls/regionListCtrl.js  |  56 ++++
 .../main/webapp/app/apps/hadoop_metric/index.js | 264 ++++++++++++++++++-
 .../apps/hadoop_metric/partials/overview.html   |  36 ++-
 .../partials/region/regionDetail.html           | 105 ++++++++
 .../partials/region/regionList.html             |  53 ++++
 .../app/apps/hadoop_metric/style/index.css      |   7 +-
 .../hadoop_metric/widgets/availabilityChart.js  |   2 +-
 11 files changed, 897 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/resources/META-INF/providers/org.apache.eagle.metric.HadoopMetricMonitorAppProdiver.xml
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/resources/META-INF/providers/org.apache.eagle.metric.HadoopMetricMonitorAppProdiver.xml
 
b/eagle-hadoop-metric/src/main/resources/META-INF/providers/org.apache.eagle.metric.HadoopMetricMonitorAppProdiver.xml
index 9a32eda..7b7c273 100644
--- 
a/eagle-hadoop-metric/src/main/resources/META-INF/providers/org.apache.eagle.metric.HadoopMetricMonitorAppProdiver.xml
+++ 
b/eagle-hadoop-metric/src/main/resources/META-INF/providers/org.apache.eagle.metric.HadoopMetricMonitorAppProdiver.xml
@@ -20,6 +20,12 @@
     <type>HADOOP_METRIC_MONITOR</type>
     <name>Hadoop Metrics Monitor</name>
     <viewPath>/apps/hadoop_metric</viewPath>
+    <dependencies>
+        <dependency>
+            <type>TOPOLOGY_HEALTH_CHECK_APP</type>
+            <required>true</required>
+        </dependency>
+    </dependencies>
     <configuration>
         <!-- data fromStream configurations -->
         <property>
@@ -84,6 +90,16 @@
             <description>Kafka Transaction Status Update MS</description>
             <required>false</required>
         </property>
+        <property>
+            <name>service.host</name>
+            <displayName>Eagle Service Host</displayName>
+            <description>Set additional eagle service host, default: using 
current host</description>
+        </property>
+        <property>
+            <name>service.port</name>
+            <displayName>Eagle Service Port</displayName>
+            <description>Set additional eagle service port, default: using 
current port</description>
+        </property>
     </configuration>
     <streams>
         <stream>

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/config.json
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/config.json 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/config.json
new file mode 100644
index 0000000..185e791
--- /dev/null
+++ b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/config.json
@@ -0,0 +1,68 @@
+{
+       "master": {
+               "nonheap": "hadoop.memory.nonheapmemoryusage.used",
+               "heap": "hadoop.memory.heapmemoryusage.used",
+               "averageload": "hadoop.hbase.master.server.averageload",
+               "ritcount": "hadoop.hbase.master.assignmentmanger.ritcount",
+               "ritcountoverthreshold": 
"hadoop.hbase.master.assignmentmanger.ritcountoverthreshold",
+               "AssignNumOps": 
"hadoop.hbase.master.assignmentmanger.assign_num_ops",
+               "AssignMin": "hadoop.hbase.master.assignmentmanger.assign_min",
+               "AssignMax": "hadoop.hbase.master.assignmentmanger.assign_max",
+               "AssignPercentile75th": 
"hadoop.hbase.master.assignmentmanger.assign_75th_percentile",
+               "AssignPercentile95th": 
"hadoop.hbase.master.assignmentmanger.assign_95th_percentile",
+               "AssignPercentile99th": 
"hadoop.hbase.master.assignmentmanger.assign_99th_percentile",
+               "BulkAssignNum_ops": 
"hadoop.hbase.master.assignmentmanger.bulkassign_num_ops",
+               "BulkAssignMin": 
"hadoop.hbase.master.assignmentmanger.bulkassign_min",
+               "BulkAssignMax": 
"hadoop.hbase.master.assignmentmanger.bulkassign_max",
+               "BulkAssignPercentile75th": 
"hadoop.hbase.master.assignmentmanger.bulkassign_75th_percentile",
+               "BulkAssignPercentile95th": 
"hadoop.hbase.master.assignmentmanger.bulkassign_95th_percentile",
+               "BulkAssignPercentile99th": 
"hadoop.hbase.master.assignmentmanger.bulkassign_99th_percentile",
+               "BalancerClusterNum_ops": 
"hadoop.hbase.master.balancer.balancercluster_num_ops",
+               "BalancerClusterMin": 
"hadoop.hbase.master.balancer.balancercluster_min",
+               "BalancerClusterMax": 
"hadoop.hbase.master.balancer.balancercluster_max",
+               "BalancerClusterPercentile75th": 
"hadoop.hbase.master.balancer.balancercluster_75th_percentile",
+               "BalancerClusterPercentile95th": 
"hadoop.hbase.master.balancer.balancercluster_95th_percentile",
+               "BalancerClusterPercentile99th": 
"hadoop.hbase.master.balancer.balancercluster_99th_percentile",
+               "HlogSplitTimeMin": 
"hadoop.hbase.master.filesystem.hlogsplittime_min",
+               "HlogSplitTimeMax": 
"hadoop.hbase.master.filesystem.hlogsplittime_max",
+               "HlogSplitTimePercentile75th": 
"hadoop.hbase.master.filesystem.hlogsplittime_75th_percentile",
+               "HlogSplitTimePercentile95th": 
"hadoop.hbase.master.filesystem.hlogsplittime_95th_percentile",
+               "HlogSplitTimePercentile99th": 
"hadoop.hbase.master.filesystem.hlogsplittime_99th_percentile",
+               "HlogSplitSizeMin": 
"hadoop.hbase.master.filesystem.hlogsplitsize_min",
+               "HlogSplitSizeMax": 
"hadoop.hbase.master.filesystem.hlogsplitsize_max",
+               "MetaHlogSplitTimeMin": 
"hadoop.hbase.master.filesystem.metahlogsplittime_min",
+               "MetaHlogSplitTimeMax": 
"hadoop.hbase.master.filesystem.metahlogsplittime_max",
+               "MetaHlogSplitTimePercentile75th": 
"hadoop.hbase.master.filesystem.metahlogsplittime_75th_percentile",
+               "MetaHlogSplitTimePercentile95th": 
"hadoop.hbase.master.filesystem.metahlogsplittime_95th_percentile",
+               "MetaHlogSplitTimePercentile99th": 
"hadoop.hbase.master.filesystem.metahlogsplittime_99th_percentile",
+               "MetaHlogSplitSizeMin": 
"hadoop.hbase.master.filesystem.metahlogsplitsize_min",
+               "MetaHlogSplitSizeMax": 
"hadoop.hbase.master.filesystem.metahlogsplitsize_max"
+       },
+       "regionserver": {
+               "nonheap" : "hadoop.memory.nonheapmemoryusage.used",
+               "heap" : "hadoop.memory.heapmemoryusage.used",
+               "directmemory" : "hadoop.bufferpool.direct.memoryused",
+               "GC count" : "hadoop.hbase.jvm.gccount",
+               "GC TimeMillis" : "hadoop.hbase.jvm.gctimemillis",
+               "QueueSize" : "hadoop.hbase.ipc.ipc.queuesize",
+               "NumCallsInGeneralQueue" : 
"hadoop.hbase.ipc.ipc.numcallsingeneralqueue",
+               "NumActiveHandler" : "hadoop.hbase.ipc.ipc.numactivehandler",
+               "IPC Queue Time (99th" : 
"hadoop.hbase.ipc.ipc.queuecalltime_99th_percentile",
+               "IPC Process Time (99th" : 
"hadoop.hbase.ipc.ipc.processcalltime_99th_percentile",
+               "QueueCallTime_num_ops" : 
"hadoop.hbase.ipc.ipc.queuecalltime_num_ops",
+               "ProcessCallTime_num_ops" : 
"hadoop.hbase.ipc.ipc.processcalltime_num_ops",
+               "RegionCount" : "hadoop.hbase.regionserver.server.regioncount",
+               "StoreCount" : "hadoop.hbase.regionserver.server.storecount",
+               "MemStoreSize" : 
"hadoop.hbase.regionserver.server.memstoresize",
+               "StoreFileSize" : 
"hadoop.hbase.regionserver.server.storefilesize",
+               "TotalRequestCount" : 
"hadoop.hbase.regionserver.server.totalrequestcount",
+               "ReadRequestCount" : 
"hadoop.hbase.regionserver.server.readrequestcount",
+               "WriteRequestCount" : 
"hadoop.hbase.regionserver.server.writerequestcount",
+               "SlitQueueLength" : 
"hadoop.hbase.regionserver.server.splitqueuelength",
+               "CompactionQueueLength" : 
"hadoop.hbase.regionserver.server.compactionqueuelength",
+               "FlushQueueLength" : 
"hadoop.hbase.regionserver.server.flushqueuelength",
+               "BlockCacheSize" : 
"hadoop.hbase.regionserver.server.blockcachesize",
+               "BlockCacheHitCount" : 
"hadoop.hbase.regionserver.server.blockcachehitcount",
+               "BlockCacheCountHitPercent" : 
"hadoop.hbase.regionserver.server.blockcounthitpercent"
+       }
+}

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/overview.js
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/overview.js 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/overview.js
index a02bed3..e10a0ce 100644
--- 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/overview.js
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/overview.js
@@ -21,52 +21,154 @@
         * `register` without params will load the module which using require
         */
        register(function (hadoopMetricApp) {
-               hadoopMetricApp.controller("overviewCtrl", function ($scope, 
PageConfig) {
+               hadoopMetricApp.controller("overviewCtrl", function ($q, 
$wrapState, $scope, PageConfig, METRIC, Time) {
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+                       var activeMasterInfo = 
METRIC.hbaseActiveMaster($scope.site);
+
                        PageConfig.title = 'Overview';
+                       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);
+                                               }
+                                       }
+                               }]
+                       };
+                       $scope.metricList = {};
 
-                       $scope.commonOption = {};
+                       function generateHbaseMetric(name, flag) {
+                               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);
 
-                       // Mock series data
-                       function mockMetric(name, option, count) {
-                               count = count || 1;
-                               var now = +new Date();
+                               $scope.site = $wrapState.param.siteId;
 
-                               var series = [];
-                               for (var i = 0 ; i < count ; i += 1) {
-                                       var data = [];
+                               return cache[name] = cache[name] || 
activeMasterInfo._promise.then(function (res) {
+                                               var hostname = cache[hostname] 
= cache[hostname] || res[0].tags.hostname;
+                                               $scope.defaultHostname = 
$wrapState.param.hostname || hostname;
 
-                                       for(var j = 0 ; j < 30 ; j += 1) {
-                                               data.push({x: now + j * 1000 * 
60, y: Math.random() * 100});
-                                       }
+                                               var jobCond = {
+                                                       site: $scope.site,
+                                                       component: 
"hbasemaster",
+                                                       host: 
$scope.defaultHostname
+                                               };
+                                               return 
METRIC.aggMetricsToEntities(METRIC.hbaseMetricsAggregation(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];
+                                               });
+                                       });
+                       }
 
-                                       series.push($.extend({
-                                               name: name + '_' + i,
-                                               type: 'line',
-                                               data: data,
-                                               showSymbol: false,
-                                       }, option));
-                               }
+                       function mergeMetricToOneSeries(metricTitle, metrics, 
legendName, dataOption, option) {
+                               var series = [];
 
+                               $.each(metrics, function (i, metricMap) {
+                                       if(typeof metricMap !== 'undefined') {
+                                               
series.push(METRIC.metricsToSeries(legendName[i], metricMap[0], option));
+                                       }
+                               });
                                return {
-                                       title: name,
-                                       series: series
+                                       title: metricTitle,
+                                       series: series,
+                                       option: dataOption || {}
                                };
                        }
 
-                       $scope.metricList = [
-                               mockMetric('name1', {}),
-                               mockMetric('name2', {smooth:true}),
-                               mockMetric('name3', {areaStyle: {normal: {}}}),
-                               mockMetric('name4', {type: 'bar'}),
-                               mockMetric('name1', {}, 2),
-                               mockMetric('name2', {smooth:true}, 2),
-                               mockMetric('name3', {areaStyle: {normal: {}}, 
stack: 'one'}, 2),
-                               mockMetric('name4', {type: 'bar', stack: 
'one'}, 2),
-                               mockMetric('name1', {}, 3),
-                               mockMetric('name2', {smooth:true}, 3),
-                               mockMetric('name3', {areaStyle: {normal: {}}, 
stack: 'one'}, 3),
-                               mockMetric('name4', {type: 'bar', stack: 
'one'}, 3),
-                       ];
+                       // TODO: Optimize the chart count
+                       // TODO: ECharts dynamic refresh series bug: 
https://github.com/ecomfe/echarts/issues/4033
+
+
+                       $scope.refresh = function () {
+                               var hbaseservers = 
METRIC.hbasehostStatus({site: $scope.site});
+                               var metricspromies = [];
+                               METRIC.getMetricObj().then(function (res) {
+                                       var masterMetricList = res.master;
+                                       for (var metricKey in masterMetricList) 
{
+                                               
metricspromies.push(generateHbaseMetric(masterMetricList[metricKey], 
metricKey));
+                                       }
+                                       $q.all(metricspromies).then(function 
(resp) {
+                                               var metricObj = {};
+                                               for(var i=0; i < resp.length; 
i+=1) {
+                                                       metricObj[resp[i][0]] = 
resp[i][1];
+                                               }
+                                               return metricObj;
+                                       }).then(function (seriesObj) {
+                                               $scope.metricList = [
+                                                       
mergeMetricToOneSeries("MemoryUsage", [seriesObj["nonheap"], 
seriesObj["heap"]], ["nonheap", "heap"], storageOption, {areaStyle: {normal: 
{}}}),
+                                                       
mergeMetricToOneSeries("Master Averageload", [seriesObj["averageload"]], 
["averageload"]),
+                                                       
mergeMetricToOneSeries("Ritcount", [seriesObj["ritcount"], 
seriesObj["ritcountoverthreshold"]], ["ritcount", "ritcountoverthreshold"]),
+                                                       
mergeMetricToOneSeries("Assign", [seriesObj["AssignNumOps"], 
seriesObj["AssignMin"], seriesObj["AssignMax"]], ["numOps", "Min", "Max"]),
+                                                       
mergeMetricToOneSeries("Assign Percentile", [seriesObj["AssignPercentile75th"], 
seriesObj["AssignPercentile95th"], seriesObj["AssignPercentile99th"]], ["75th", 
"95th", "99th"]),
+                                                       
mergeMetricToOneSeries("BulkAssign", [seriesObj["BulkAssignNum_ops"], 
seriesObj["BulkAssignMin"], seriesObj["BulkAssignMax"]], ["num_ops", "min", 
"max"]),
+                                                       
mergeMetricToOneSeries("BulkAssign Percentile", 
[seriesObj["BulkAssignPercentile75th"], seriesObj["BulkAssignPercentile95th"], 
seriesObj["BulkAssignPercentile99th"]], ["75th", "95th", "99th"]),
+                                                       
mergeMetricToOneSeries("BalancerCluster", [seriesObj["BalancerClusterNum_ops"], 
seriesObj["BalancerClusterMin"], seriesObj["BalancerClusterMax"]], ["num_ops", 
"min", "max"]),
+                                                       
mergeMetricToOneSeries("BalancerCluster Percentile", 
[seriesObj["BalancerClusterPercentile75th"], 
seriesObj["BalancerClusterPercentile95th"], 
seriesObj["BalancerClusterPercentile99th"]], ["75th", "95th", "99th"]),
+                                                       
mergeMetricToOneSeries("HlogSplitTime", [seriesObj["HlogSplitTimeMin"], 
seriesObj["HlogSplitTimeMax"]], ["HlogSplitTime_min", "HlogSplitTime_max"]),
+                                                       
mergeMetricToOneSeries("HlogSplitTime Percentile", 
[seriesObj["HlogSplitTimePercentile75th"], 
seriesObj["HlogSplitTimePercentile95th"], 
seriesObj["HlogSplitTimePercentile99th"]], ["75th", "95th", "99th"]),
+                                                       
mergeMetricToOneSeries("HlogSplitSize", [seriesObj["HlogSplitSizeMin"], 
seriesObj["HlogSplitSizeMax"]], ["Min", "Max"]),
+                                                       
mergeMetricToOneSeries("MetaHlogSplitTime", [seriesObj["MetaHlogSplitTimeMin"], 
seriesObj["MetaHlogSplitTimeMax"]], ["Min", "Max"]),
+                                                       
mergeMetricToOneSeries("MetaHlogSplitTime Percentile", 
[seriesObj["MetaHlogSplitTimePercentile75th"], 
seriesObj["MetaHlogSplitTimePercentile95th"], 
seriesObj["MetaHlogSplitTimePercentile99th"]], ["75th", "95th", "99th"]),
+                                                       
mergeMetricToOneSeries("MetaHlogSplitSize", [seriesObj["MetaHlogSplitSizeMin"], 
seriesObj["MetaHlogSplitSizeMax"]], ["Min", "Max"])
+                                               ];
+                                       });
+                               });
+
+                               hbaseservers._promise.then(function (res) {
+                                       var regionhealtynum = 0;
+                                       var regiontotal = 0;
+                                       var hmasteractive;
+                                       var hmasterstandby;
+                                       $.each(res, function (i, server) {
+                                               var role = server.tags.role;
+                                               var status = server.status;
+                                               if (role === "regionserver") {
+                                                       regiontotal++;
+                                                       if (status === "live") {
+                                                               
regionhealtynum++;
+                                                       }
+                                               }
+                                               else if (role === "hmaster") {
+                                                       if (status === 
"active") {
+                                                               hmasteractive = 
server;
+                                                       } else {
+                                                               hmasterstandby 
= server;
+                                                       }
+
+                                               }
+                                       });
+                                       $scope.regionhealtynum = 
regionhealtynum;
+                                       $scope.regiontotal = regiontotal;
+                                       $scope.hmasteractive = hmasteractive;
+                                       $scope.hmasterstandby = hmasterstandby;
+                               })
+                       };
+
+
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
                });
        });
 })();
+//# sourceURL=overview.js

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionDetailCtrl.js
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionDetailCtrl.js
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionDetailCtrl.js
new file mode 100644
index 0000000..1f8c40d
--- /dev/null
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionDetailCtrl.js
@@ -0,0 +1,164 @@
+/*
+ * 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 (hadoopMetricApp) {
+               hadoopMetricApp.controller("regionDetailCtrl", function ($q, 
$wrapState, $scope, PageConfig, Time, METRIC) {
+                       var cache = {};
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.hostname = $wrapState.param.hostname;
+                       PageConfig.title = 'RegionServer ' + "(" + 
$scope.hostname + ")";
+                       $scope.metricList = [];
+                       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 gctimeoption = {
+                               legend: {
+                                       x: 'center', y: 'bottom'
+                               },
+                               yAxis: [{
+                                       axisLabel: {
+                                               formatter: function (value) {
+                                                       return value / 1000 + ' 
S';
+                                               }
+                                       }
+                               }]
+                       };
+
+                       $scope.refresh = function () {
+                               var startTime = Time.startTime();
+                               var endTime = Time.endTime();
+                               var metricspromies = [];
+                               METRIC.getMetricObj().then(function (res) {
+                                       console.log(res.regionserver);
+                                       var masterMetricList = res.regionserver;
+                                       for (var metricKey in masterMetricList) 
{
+                                               
metricspromies.push(generateHbaseMetric(masterMetricList[metricKey], startTime, 
endTime, metricKey));
+                                       }
+                                       $q.all(metricspromies).then(function 
(resp) {
+                                               var metricObj = {};
+                                               for(var i=0; i < resp.length; 
i+=1) {
+                                                       metricObj[resp[i][0]] = 
resp[i][1];
+                                               }
+                                               return metricObj;
+                                       }).then(function (seriesObj) {
+                                               $scope.metricList = [];
+                                               
$scope.metricList.push(mergeSeries("Memory Usage", [seriesObj["nonheap"], 
seriesObj["heap"]], ["nonheap", "heap"], sizeoption));
+                                               
$scope.metricList.push(mergeSeries("Direct Memory Usage", 
[seriesObj["directmemory"]], ["directmemory"], sizeoption));
+                                               
$scope.metricList.push(mergeSeries("GC count", [seriesObj["GC count"]], ["GC 
count"], {}));
+                                               
$scope.metricList.push(mergeSeries("GC TimeMillis", [seriesObj["GC 
TimeMillis"]], ["GC TimeMillis"], gctimeoption));
+                                               
$scope.metricList.push(mergeSeries("QueueSize", [seriesObj["QueueSize"]], 
["QueueSize"], {}));
+                                               
$scope.metricList.push(mergeSeries("NumCallsInGeneralQueue", 
[seriesObj["NumCallsInGeneralQueue"]], ["NumCallsInGeneralQueue"], {}));
+                                               
$scope.metricList.push(mergeSeries("NumActiveHandler", 
[seriesObj["NumActiveHandler"]], ["NumActiveHandler"], {}));
+                                               
$scope.metricList.push(mergeSeries("IPC Queue Time (99th)", [seriesObj["IPC 
Queue Time (99th)"]], ["IPC Queue Time (99th)"], {}));
+                                               
$scope.metricList.push(mergeSeries("IPC Process Time (99th)", [seriesObj["IPC 
Process Time (99th)"]], ["IPC Process Time (99th)"], {}));
+                                               
$scope.metricList.push(mergeSeries("QueueCallTime_num_ops", 
[seriesObj["QueueCallTime_num_ops"]], ["QueueCallTime_num_ops"], {}));
+                                               
$scope.metricList.push(mergeSeries("ProcessCallTime_num_ops", 
[seriesObj["ProcessCallTime_num_ops"]], ["ProcessCallTime_num_ops"], {}));
+                                               
$scope.metricList.push(mergeSeries("RegionCount", [seriesObj["RegionCount"]], 
["RegionCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("StoreCount", [seriesObj["StoreCount"]], 
["StoreCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("MemStoreSize", [seriesObj["MemStoreSize"]], 
["MemStoreSize"], sizeoption));
+                                               
$scope.metricList.push(mergeSeries("StoreFileSize", 
[seriesObj["StoreFileSize"]], ["StoreFileSize"], sizeoption));
+                                               
$scope.metricList.push(mergeSeries("TotalRequestCount", 
[seriesObj["TotalRequestCount"]], ["TotalRequestCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("ReadRequestCount", 
[seriesObj["ReadRequestCount"]], ["ReadRequestCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("WriteRequestCount", 
[seriesObj["WriteRequestCount"]], ["WriteRequestCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("SlitQueueLength", 
[seriesObj["SlitQueueLength"]], ["SlitQueueLength"], {}));
+                                               
$scope.metricList.push(mergeSeries("CompactionQueueLength", 
[seriesObj["CompactionQueueLength"]], ["CompactionQueueLength"], {}));
+                                               
$scope.metricList.push(mergeSeries("FlushQueueLength", 
[seriesObj["FlushQueueLength"]], ["FlushQueueLength"], {}));
+                                               
$scope.metricList.push(mergeSeries("BlockCacheSize", 
[seriesObj["BlockCacheSize"]], ["BlockCacheSize"], sizeoption));
+                                               
$scope.metricList.push(mergeSeries("BlockCacheHitCount", 
[seriesObj["BlockCacheHitCount"]], ["BlockCacheHitCount"], {}));
+                                               
$scope.metricList.push(mergeSeries("BlockCacheCountHitPercent", 
[seriesObj["BlockCacheCountHitPercent"]], ["BlockCacheCountHitPercent"], {}));
+                                       });
+                               });
+
+                               METRIC.regionserverStatus($scope.hostname, 
$scope.site)._promise.then(function (res) {
+                                       $scope.regionstatus = res;
+                               });
+                       };
+                       Time.onReload(function () {
+                               cache = {};
+                               $scope.refresh();
+                       }, $scope);
+                       $scope.refresh();
+
+
+                       function generateHbaseMetric(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 
METRIC.aggMetricsToEntities(METRIC.hbaseMetricsAggregation(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(METRIC.metricsToSeries(linename[i], metric, option));
+                                               }
+                                       });
+                               });
+                               return {
+                                       title: title,
+                                       series: series,
+                                       option: option || {}
+                               };
+                       }
+               });
+       });
+})
+();

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionListCtrl.js
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionListCtrl.js
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionListCtrl.js
new file mode 100644
index 0000000..bc7abd9
--- /dev/null
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/ctrls/regionListCtrl.js
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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 (hadoopMetricApp) {
+
+               hadoopMetricApp.controller("regionListCtrl", function 
($wrapState, $scope, PageConfig, METRIC) {
+
+                       // Initialization
+                       PageConfig.title = "HBASE RegionServers";
+                       $scope.tableScope = {};
+                       $scope.live = METRIC.STATUS_LIVE;
+                       $scope.dead = METRIC.STATUS_DEAD;
+                       $scope.site = $wrapState.param.siteId;
+                       $scope.searchPathList = [["tags", "hostname"], ["tags", 
"rack"], ["tags", "site"], ["status"]];
+                       $scope.regionserverList = 
METRIC.regionserverList($scope.site);
+
+               });
+       });
+})();

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/index.js
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/index.js 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/index.js
index 954cd6d..b81dfe4 100644
--- a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/index.js
+++ b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/index.js
@@ -23,24 +23,278 @@
        var hadoopMetricApp = register(['ngRoute', 'ngAnimate', 'ui.router', 
'eagle.service']);
 
        hadoopMetricApp.route("HadoopMetric", {
-               url: "/hadoopMetric/",
+               url: "/hadoopMetric?startTime&endTime",
                site: true,
                templateUrl: "partials/overview.html",
                controller: "overviewCtrl",
+               resolve: {time: true}
        }).route("HadoopMetric_HDFS", {
                url: "/hadoopMetric/hdfs",
                site: true,
                templateUrl: "partials/hdfs/index.html",
                controller: "hdfsCtrl",
+               resolve: {time: true}
+       }).route("regionDetail", {
+               url: "/hadoopMetric/regionDetail/:hostname",
+               site: true,
+               templateUrl: "partials/region/regionDetail.html",
+               controller: "regionDetailCtrl",
+               resolve: {time: true}
+       }).route("regionList", {
+               url: "/hadoopMetric/regionList",
+               site: true,
+               templateUrl: "partials/region/regionList.html",
+               controller: "regionListCtrl"
+       }).route("masterDetail", {
+               url: "/hadoopMetric/:hostname?startTime&endTime",
+               site: true,
+               reloadOnSearch: false,
+               templateUrl: "partials/overview.html",
+               controller: "overviewCtrl",
+               resolve: {time: true}
        });
 
-       hadoopMetricApp.portal({name: "Services", icon: "heartbeat", list: [
-               {name: "Overview", path: "hadoopMetric/"},
-               {name: "HDFS", path: "hadoopMetric/hdfs"},
-       ]}, true);
+       hadoopMetricApp.portal({
+               name: "Services", icon: "heartbeat", list: [
+                       {name: "Overview", path: "hadoopMetric"},
+                       {name: "HDFS", path: "hadoopMetric/hdfs"}
+               ]
+       }, true);
+
+       hadoopMetricApp.service("METRIC", function ($q, $http, Time, Site, 
Application) {
+               var METRIC = window._METRIC = {};
+               METRIC.STATUS_LIVE = "live";
+               METRIC.STATUS_DEAD = "dead";
+               METRIC.QUERY_HBASE_METRICS = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]{*}&metricName=${metric}&pageSize=${limit}';
+               METRIC.QUERY_HBASE_METRICS_WITHTIME = 
'${baseURL}/rest/entities?query=GenericMetricService[${condition}]{*}&metricName=${metric}&pageSize=${limit}&startTime=${startTime}&endTime=${endTime}';
+               METRIC.QUERY_HBASE_INSTANCE = 
'${baseURL}/rest/entities?query=HbaseServiceInstance[${condition}]{*}&pageSize=${limit}';
+               METRIC.QUERY_HBASE_METRICS_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 = METRIC.getQuery = function (queryName, siteId) {
+                       var baseURL;
+                       siteId = siteId || Site.current().siteId;
+                       var app = Application.find("HADOOP_METRIC_MONITOR", 
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(METRIC["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(",") : "*";
+               }
+
+               METRIC.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 || {});
+               };
+
+               METRIC.get = function (url, params) {
+                       return $http({
+                               url: url,
+                               method: "GET",
+                               params: params
+                       });
+               };
+
+               METRIC.condition = function (condition) {
+                       return $.map(condition, function (value, key) {
+                               return "@" + key + '="' + value + '"';
+                       }).join(" AND ");
+               };
+
+
+               METRIC.hbaseMetrics = function (condition, metric, startTime, 
endTime, limit) {
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               startTime: Time.format(startTime),
+                               endTime: Time.format(endTime),
+                               metric: metric,
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_METRICS_WITHTIME"), config);
+                       return wrapList(METRIC.get(metrics_url));
+               };
+
+               METRIC.hbaseMetricsAggregation = 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: METRIC.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("HBASE_METRICS_INTERVAL"), config);
+                       var _list = wrapList(METRIC.get(metrics_url));
+                       _list._aggInfo = {
+                               groups: groups,
+                               startTime: Time(startTime).valueOf(),
+                               interval: intervalMin * 60 * 1000
+                       };
+                       _list._promise.then(function () {
+                               _list.reverse();
+                       });
+                       return _list;
+               };
+
+               METRIC.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;
+               };
+
+
+               METRIC.hbasehostStatus = function (condition, limit) {
+                       var config = {
+                               condition: METRIC.condition(condition),
+                               limit: limit || 10000
+                       };
+
+                       var metrics_url = 
common.template(getQuery("HBASE_INSTANCE"), config);
+                       return wrapList(METRIC.get(metrics_url));
+               };
+
+               METRIC.hbaseActiveMaster = function (siteId) {
+                       var condition = {
+                               site: siteId,
+                               role: "hmaster",
+                               status: "active"
+                       };
+                       return METRIC.hbasehostStatus(condition, 1);
+               };
+
+               METRIC.regionserverStatus = function (hostname, siteid) {
+                       var hoststateinfo;
+                       var condition = {
+                               site: siteid,
+                               role: "regionserver",
+                               hostname: hostname
+                       };
+                       hoststateinfo = METRIC.hbasehostStatus(condition, 1);
+                       return hoststateinfo;
+               };
+
+               METRIC.regionserverList = function (siteid) {
+                       var hoststateinfos;
+                       var condition = {
+                               site: siteid,
+                               role: "regionserver"
+                       };
+                       hoststateinfos = METRIC.hbasehostStatus(condition);
+                       return hoststateinfos;
+               };
+
+               METRIC.getMetricObj = function () {
+                       var deferred = $q.defer();
+                       
$http.get("apps/hadoop_metric/config.json").success(function (resp) {
+                               deferred.resolve(resp);
+                       });
+                       return deferred.promise;
+               };
+               return METRIC;
+       });
 
        hadoopMetricApp.requireCSS("style/index.css");
        hadoopMetricApp.require("widgets/availabilityChart.js");
        hadoopMetricApp.require("ctrls/overview.js");
        hadoopMetricApp.require("ctrls/hdfs.js");
+       hadoopMetricApp.require("ctrls/regionDetailCtrl.js");
+       hadoopMetricApp.require("ctrls/regionListCtrl.js");
 })();

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/overview.html
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/overview.html
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/overview.html
index cb4d01c..13caebf 100644
--- 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/overview.html
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/overview.html
@@ -20,11 +20,37 @@
        <div class="box-header with-border">
                <span class="fa fa-television"></span>
                <h3 class="box-title">
-                       Summary
+                       Service Summary Information
                </h3>
        </div>
        <div class="box-body">
-               TODO: Your summary
+
+               <table class="table table-striped">
+                       <tbody>
+                       <tr ng-if="regiontotal > 0">
+                               <th>RegionServer Status</th>
+                               <td class="text-break">
+                                       <a ui-sref="regionList({siteId: site})" 
target="_blank">{{regiontotal}} RegionServers</a>
+                                       <span class="label 
label-success">{{regionhealtynum}} Healthy</span>
+                                       <span class="label 
label-danger">{{regiontotal - regionhealtynum}} UnHealthy</span>
+                               </td>
+                       </tr>
+                       <tr ng-if="hmasteractive">
+                               <th>Active Hmaster Status</th>
+                               <td class="text-break">
+                                       <span ng-if="defaultHostname !== 
hmasteractive.tags.hostname" class="label label-success">(<a 
class="hadoopMetric-summary-a" ui-sref="masterDetail({siteId: site, hostname: 
hmasteractive.tags.hostname})">{{hmasteractive.tags.hostname}}</a>) 
Healthy</span>
+                                       <span ng-if="defaultHostname === 
hmasteractive.tags.hostname" class="label 
label-success">({{hmasteractive.tags.hostname}}) Healthy</span>
+                               </td>
+                       </tr>
+                       <tr ng-if="hmasterstandby">
+                               <th>Standby Hmaster Status</th>
+                               <td class="text-break">
+                                       <span ng-if="defaultHostname !== 
hmasterstandby.tags.hostname" class="label label-success">(<a 
class="hadoopMetric-summary-a" ui-sref="masterDetail({siteId: site, hostname: 
hmasterstandby.tags.hostname})">{{hmasterstandby.tags.hostname}}</a>) 
Healthy</span>
+                                       <span ng-if="defaultHostname === 
hmasterstandby.tags.hostname" class="label 
label-success">({{hmasterstandby.tags.hostname}}) Healthy</span>
+                               </td>
+                       </tr>
+                       </tbody>
+               </table>
        </div>
 </div>
 
@@ -33,6 +59,7 @@
                <span class="fa fa-line-chart"></span>
                <h3 class="box-title">
                        Metrics
+                       <span>({{defaultHostname}})</span>
                </h3>
        </div>
        <div class="box-body no-padding">
@@ -40,10 +67,11 @@
                        <div class="col-sm-6 col-md-4 col-lg-3" 
ng-repeat="metric in metricList track by $index">
                                <div class="hadoopMetric-chart">
                                        <h3>{{metric.title}}</h3>
-                                       <div chart 
class="hadoopMetric-chart-container" series="metric.series" 
option="commonOption"></div>
-                                       </div>
+                                       <div chart 
class="hadoopMetric-chart-container" series="metric.series"
+                                                option="metric.option"></div>
                                </div>
                        </div>
                </div>
        </div>
 </div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionDetail.html
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionDetail.html
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionDetail.html
new file mode 100644
index 0000000..e95bd24
--- /dev/null
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionDetail.html
@@ -0,0 +1,105 @@
+<!--
+  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="(regionstatus || []).length !== 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break">
+                                       <span 
ng-if="regionstatus[0].status==='live'" class="label 
label-success">Healthy</span>
+                                       <span 
ng-if="regionstatus[0].status!=='live'" class="label 
label-danger">UnHealthy</span>
+                               </td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td 
class="text-break">{{regionstatus[0].tags.rack}}</td>
+                       </tr>
+                       <tr>
+                               <th>MaxHeap</th>
+                               <td 
class="text-break">{{regionstatus[0].maxHeapMB}} MB</td>
+                       </tr>
+                       <tr>
+                               <th>UsedHeap</th>
+                               <td 
class="text-break">{{regionstatus[0].usedHeapMB}} MB</td>
+                       </tr>
+                       <tr>
+                               <th>NumRegions</th>
+                               <td 
class="text-break">{{regionstatus[0].numRegions}}</td>
+                       </tr>
+                       <tr>
+                               <th>NumRequests</th>
+                               <td 
class="text-break">{{regionstatus[0].numRequests}}</td>
+                       </tr>
+                       </tbody>
+                       <tbody ng-if="regionstatus.length === 0">
+                       <tr>
+                               <th>Status</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>Rack</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>MaxHeap</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>UsedHeap</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumRegions</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</span></td>
+                       </tr>
+                       <tr>
+                               <th>NumRequests</th>
+                               <td class="text-break"><span class="label 
label-danger">Unknow</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-3" 
ng-repeat="metric in metricList track by $index">
+                               <div class="hadoopMetric-chart">
+                                       <h3>{{metric.title}}</h3>
+                                       <div chart 
class="hadoopMetric-chart-container" series="metric.series" 
option="metric.option"></div>
+                               </div>
+                       </div>
+               </div>
+       </div>
+</div>
+</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionList.html
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionList.html
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionList.html
new file mode 100644
index 0000000..507de72
--- /dev/null
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/partials/region/regionList.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="!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})" 
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/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/style/index.css
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/style/index.css 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/style/index.css
index 947120b..6ae1ea1 100644
--- a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/style/index.css
+++ b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/style/index.css
@@ -46,7 +46,7 @@
 
 .hadoopMetric-widget {
        width: 100%;
-       box-shadow: 0 1px 1px rgba(0,0,0,0.1);
+       box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
        border-radius: 2px;
        padding: 10px;
 }
@@ -59,3 +59,8 @@
 .hadoopMetric-widget .hadoopMetric-chart-container {
        height: 100px;
 }
+
+.hadoopMetric-summary-a {
+       color: #fff;
+}
+

http://git-wip-us.apache.org/repos/asf/eagle/blob/257a3517/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/widgets/availabilityChart.js
----------------------------------------------------------------------
diff --git 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/widgets/availabilityChart.js
 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/widgets/availabilityChart.js
index fddcb88..75e6835 100644
--- 
a/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/widgets/availabilityChart.js
+++ 
b/eagle-hadoop-metric/src/main/webapp/app/apps/hadoop_metric/widgets/availabilityChart.js
@@ -97,7 +97,7 @@
                                $element.append(
                                        $("<div hadoop-metric-widget 
data-type='" + serviceType + "'>")
                                );
-                       }
+                       };
                }
 
                hadoopMetricApp.widget("availabilityHDFSChart", 
withType('HDFS'), true);

Reply via email to