You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eagle.apache.org by ji...@apache.org on 2017/01/06 03:26:00 UTC
eagle git commit: [EAGLE-845] JMX Dashboard
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 <ch...@gmail.com>
Author: r7raul1984 <ta...@yhd.com>
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 <ch...@gmail.com>
Authored: Fri Jan 6 11:25:44 2017 +0800
Committer: zombieJ <sm...@gmail.com>
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);