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/02/14 08:07:36 UTC

eagle git commit: [EAGLE-868] Refactor metric chart render process to improve user experience

Repository: eagle
Updated Branches:
  refs/heads/master f9bce3084 -> 1cfff2b9a


[EAGLE-868] Refactor metric chart render process to improve user experience

[EAGLE-868] Refactor metric chart render process to improve user experience
- show "data loading icon" for each chart one by one
- load metric data query for each chart
- reader metric data into metric chart when response returned and remove "data loading icon" one by one

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

Author: r7raul1984 <ta...@yhd.com>

Closes #792 from r7raul1984/EAGLE-868.


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

Branch: refs/heads/master
Commit: 1cfff2b9a9ade5dd7c9fd1b9c5e8f5928963da85
Parents: f9bce30
Author: r7raul1984 <ta...@yhd.com>
Authored: Tue Feb 14 16:07:28 2017 +0800
Committer: zombieJ <sm...@gmail.com>
Committed: Tue Feb 14 16:07:28 2017 +0800

----------------------------------------------------------------------
 .../app/apps/hadoop_metric/ctrls/overview.js    | 170 ++++++++++++----
 .../hadoop_metric/ctrls/regionDetailCtrl.js     | 201 +++++++++++++++----
 .../apps/hadoop_metric/partials/overview.html   |  14 +-
 .../partials/region/regionDetail.html           |  14 +-
 .../hadoop_metric/widgets/availabilityChart.js  |   8 +-
 5 files changed, 315 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/eagle/blob/1cfff2b9/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 406adf2..6e7df0b 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
@@ -47,7 +47,7 @@
 					}
 				}]
 			};
-			$scope.metricList = {};
+
 
 			function generateHbaseMetric(name, flag) {
 				var startTime = Time.startTime();
@@ -58,8 +58,7 @@
 				var trendEndTime = Time.align(endTime, interval);
 
 				$scope.site = $wrapState.param.siteId;
-
-				return cache[name] = cache[name] || activeMasterInfo._promise.then(function (res) {
+				var result = cache[name] || activeMasterInfo._promise.then(function (res) {
 						var hostname = cache[hostname] = cache[hostname] || res[0].tags.hostname;
 						$scope.defaultHostname = $wrapState.param.hostname || hostname;
 
@@ -76,6 +75,7 @@
 								return [metricFlag, list];
 							});
 					});
+				return result;
 			}
 
 			function mergeMetricToOneSeries(metricTitle, metrics, legendName, dataOption, option) {
@@ -89,7 +89,8 @@
 				return {
 					title: metricTitle,
 					series: series,
-					option: dataOption || {}
+					option: dataOption || {},
+					loading: false
 				};
 			}
 
@@ -112,39 +113,138 @@
 
 			// TODO: Optimize the chart count
 			// TODO: ECharts dynamic refresh series bug: https://github.com/ecomfe/echarts/issues/4033
-
-
+			$scope.chartList = [
+				{
+					name: "MemoryUsage",
+					metrics: ["nonheap", "heap"],
+					linename: ["nonheap", "heap"],
+					option: storageOption
+				},
+				{
+					name: "Master Averageload",
+					metrics: ["averageload"],
+					linename: ["averageload"],
+					option: {}
+				},
+				{
+					name: "Ritcount",
+					metrics: ["ritcount", "ritcountoverthreshold"],
+					linename: ["ritcount", "ritcountoverthreshold"],
+					option: {}
+				},
+				{
+					name: "AssignOpsNum",
+					metrics: ["AssignNumOps"],
+					linename: ["numOps"],
+					option: {}
+				},
+				{
+					name: "Assign",
+					metrics: ["AssignMin", "AssignMax", "AssignPercentile75th", "AssignPercentile95th", "AssignPercentile99th"],
+					linename: ["min", "max", "75th", "95th", "99th"],
+					option: {}
+				},
+				{
+					name: "BulkAssignOpsNum",
+					metrics: ["BulkAssignNum_ops"],
+					linename: ["num_ops"],
+					option: {}
+				},
+				{
+					name: "BulkAssign",
+					metrics: ["BulkAssignMin", "BulkAssignMax", "BulkAssignPercentile75th", "BulkAssignPercentile95th", "BulkAssignPercentile99th"],
+					linename: ["min", "max", "75th", "95th", "99th"],
+					option: {}
+				},
+				{
+					name: "BalancerClusterOpsNum",
+					metrics: ["BalancerClusterNum_ops"],
+					linename: ["num_ops"],
+					option: {}
+				},
+				{
+					name: "BalancerCluster",
+					metrics: ["BalancerClusterMin", "BalancerClusterMax", "BalancerClusterPercentile75th", "BalancerClusterPercentile95th", "BalancerClusterPercentile99th"],
+					linename: ["min", "max", "75th", "95th", "99th"],
+					option: {}
+				},
+				{
+					name: "HlogSplitTime",
+					metrics: ["HlogSplitTimeMin", "HlogSplitTimeMax"],
+					linename: ["HlogSplitTime_min", "HlogSplitTime_max"],
+					option: {}
+				},
+				{
+					name: "HlogSplitTime Percentile",
+					metrics: ["HlogSplitTimePercentile75th", "HlogSplitTimePercentile95th", "HlogSplitTimePercentile99th"],
+					linename: ["75th", "95th", "99th"],
+					option: {}
+				},
+				{
+					name: "HlogSplitSize",
+					metrics: ["HlogSplitSizeMin","HlogSplitSizeMax"],
+					linename: ["Min", "Max"],
+					option: {}
+				},
+				{
+					name: "MetaHlogSplitTime",
+					metrics: ["MetaHlogSplitTimeMin", "MetaHlogSplitTimeMax"],
+					linename: ["Min", "Max"],
+					option: {}
+				},
+				{
+					name: "MetaHlogSplitTime Percentile",
+					metrics: ["MetaHlogSplitTimePercentile75th", "MetaHlogSplitTimePercentile95th", "MetaHlogSplitTimePercentile99th"],
+					linename: ["75th", "95th", "99th"],
+					option: {}
+				},
+				{
+					name: "MetaHlogSplitSize",
+					metrics: ["MetaHlogSplitSizeMin", "MetaHlogSplitSizeMax"],
+					linename: ["Min", "Max"],
+					option: {}
+				}
+			];
+			$scope.metricList = [];
+			$.each($scope.chartList, function (i) {
+				var chart = $scope.chartList[i];
+				var chartname = chart.name;
+				$scope.metricList[chartname] = {
+					title: chartname,
+					series: {},
+					option: {},
+					loading: true,
+					promises: []
+				};
+			});
 			$scope.refresh = function () {
-				var 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("AssignOpsNum", [seriesObj["AssignNumOps"]], ["numOps"]),
-							mergeMetricToOneSeries("Assign", [seriesObj["AssignMin"], seriesObj["AssignMax"], seriesObj["AssignPercentile75th"], seriesObj["AssignPercentile95th"], seriesObj["AssignPercentile99th"]], ["min", "max", "75th", "95th", "99th"]),
-							mergeMetricToOneSeries("BulkAssignOpsNum", [seriesObj["BulkAssignNum_ops"]], ["num_ops"]),
-							mergeMetricToOneSeries("BulkAssign", [seriesObj["BulkAssignMin"], seriesObj["BulkAssignMax"], seriesObj["BulkAssignPercentile75th"], seriesObj["BulkAssignPercentile95th"], seriesObj["BulkAssignPercentile99th"]], ["min", "max", "75th", "95th", "99th"]),
-							mergeMetricToOneSeries("BalancerClusterOpsNum", [seriesObj["BalancerClusterNum_ops"]], ["num_ops"]),
-							mergeMetricToOneSeries("BalancerCluster", [seriesObj["BalancerClusterMin"], seriesObj["BalancerClusterMax"], seriesObj["BalancerClusterPercentile75th"], seriesObj["BalancerClusterPercentile95th"], seriesObj["BalancerClusterPercentile99th"]], ["min", "max", "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"])
-						];
+					$.each($scope.chartList, function (i) {
+						var chart = $scope.chartList[i];
+						var metricList = chart.metrics;
+						$.each(metricList, function (j) {
+							var metricKey = metricList[j];
+							var metricspromies = generateHbaseMetric(masterMetricList[metricKey], metricKey);
+							var chartname = chart.name;
+							$scope.metricList[chartname].promises.push(metricspromies);
+						});
+					});
+
+					$.each($scope.chartList, function (k) {
+						var chart = $scope.chartList[k];
+						var chartname = chart.name;
+						$q.all($scope.metricList[chartname].promises).then(function (resp) {
+							var series = [];
+							for (var r = 0; r < resp.length; r += 1) {
+								var rs = resp[r][1];
+								if (rs.length > 0) {
+									series.push(rs);
+								}
+							}
+							$scope.metricList[chartname] = mergeMetricToOneSeries(chartname, series, chart.linename, chart.option);
+						});
 					});
 				});
 
@@ -155,7 +255,7 @@
 				});
 				countHBaseRole($scope.site, "standby", "hmaster", ["site"], "count")._promise.then(function (res) {
 					$.map(res, function (data) {
-						$scope.hmasterstandbynum = data.value[0]
+						$scope.hmasterstandbynum = data.value[0];
 					});
 				});
 

http://git-wip-us.apache.org/repos/asf/eagle/blob/1cfff2b9/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
index 00f2c99..42d5367 100644
--- 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
@@ -26,7 +26,6 @@
 			$scope.site = $wrapState.param.siteId;
 			$scope.hostname = $wrapState.param.hostname;
 			PageConfig.title = 'RegionServer ' + "(" + $scope.hostname + ")";
-			$scope.metricList = [];
 			Time.autoRefresh = false;
 
 			var sizeoption = {
@@ -66,48 +65,171 @@
 					}
 				}]
 			};
+			$scope.chartList = [
+				{
+					name: "Memory Usage",
+					metrics: ["nonheap", "heap"],
+					option: sizeoption
+				},
+				{
+					name: "Direct Memory Usage",
+					metrics: ["directmemory"],
+					option: sizeoption
+				},
+				{
+					name: "GC count",
+					metrics: ["GCCount"],
+					option: {}
+				},
+				{
+					name: "GC TimeMillis",
+					metrics: ["GCTimeMillis"],
+					option: gctimeoption
+				},
+				{
+					name: "QueueSize",
+					metrics: ["QueueSize"],
+					option: {}
+				},
+				{
+					name: "NumCallsInGeneralQueue",
+					metrics: ["NumCallsInGeneralQueue"],
+					option: {}
+				},
+				{
+					name: "NumActiveHandler",
+					metrics: ["NumActiveHandler"],
+					option: {}
+				},
+				{
+					name: "IPC Queue Time (99th)",
+					metrics: ["IPCQueueTime99th"],
+					option: {}
+				},
+				{
+					name: "IPC Process Time (99th)",
+					metrics: ["IPCProcessTime99th"],
+					option: {}
+				},
+				{
+					name: "QueueCallTime_num_ops",
+					metrics: ["QueueCallTime_num_ops"],
+					option: {}
+				},
+				{
+					name: "ProcessCallTime_num_ops",
+					metrics: ["ProcessCallTime_num_ops"],
+					option: {}
+				},
+				{
+					name: "RegionCount",
+					metrics: ["RegionCount"],
+					option: {}
+				},
+				{
+					name: "StoreCount",
+					metrics: ["StoreCount"],
+					option: {}
+				},
+				{
+					name: "MemStoreSize",
+					metrics: ["MemStoreSize"],
+					option: sizeoption
+				},
+				{
+					name: "StoreFileSize",
+					metrics: ["StoreFileSize"],
+					option: sizeoption
+				},
+				{
+					name: "TotalRequestCount",
+					metrics: ["TotalRequestCount"],
+					option: {}
+				},
+				{
+					name: "ReadRequestCount",
+					metrics: ["ReadRequestCount"],
+					option: {}
+				},
+				{
+					name: "WriteRequestCount",
+					metrics: ["WriteRequestCount"],
+					option: {}
+				},
+				{
+					name: "SlitQueueLength",
+					metrics: ["SlitQueueLength"],
+					option: {}
+				},
+				{
+					name: "CompactionQueueLength",
+					metrics: ["CompactionQueueLength"],
+					option: {}
+				},
+				{
+					name: "FlushQueueLength",
+					metrics: ["FlushQueueLength"],
+					option: {}
+				},
+				{
+					name: "BlockCacheSize",
+					metrics: ["BlockCacheSize"],
+					option: sizeoption
+				},
+				{
+					name: "BlockCacheHitCount",
+					metrics: ["BlockCacheHitCount"],
+					option: {}
+				},
+				{
+					name: "BlockCacheCountHitPercent",
+					metrics: ["BlockCacheCountHitPercent"],
+					option: {}
+				}
+			];
 
+			$scope.metricList = [];
+			$.each($scope.chartList, function (i) {
+				var chart = $scope.chartList[i];
+				var chartname = chart.name;
+				$scope.metricList[chartname] = {
+					title: chartname,
+					series: {},
+					option: {},
+					loading: true,
+					promises: []
+				};
+			});
 			$scope.refresh = function () {
 				var startTime = Time.startTime();
 				var endTime = Time.endTime();
-				var metricspromies = [];
+
 				METRIC.getMetricObj().then(function (res) {
 					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["GCCount"]], ["GC count"], {}));
-						$scope.metricList.push(mergeSeries("GC TimeMillis", [seriesObj["GCTimeMillis"]], ["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["IPCQueueTime99th"]], ["IPC Queue Time (99th)"], {}));
-						$scope.metricList.push(mergeSeries("IPC Process Time (99th)", [seriesObj["IPCProcessTime99th"]], ["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"], {}));
+					$.each($scope.chartList, function (i) {
+						var chart = $scope.chartList[i];
+						var metricList = chart.metrics;
+						$.each(metricList, function (j) {
+							var metricKey = metricList[j];
+							var metricspromies = generateHbaseMetric(masterMetricList[metricKey], startTime, endTime, metricKey);
+							var chartname = chart.name;
+							$scope.metricList[chartname].promises.push(metricspromies);
+						});
+					});
+
+					$.each($scope.chartList, function (k) {
+						var chart = $scope.chartList[k];
+						var chartname = chart.name;
+						$q.all($scope.metricList[chartname].promises).then(function (resp) {
+							var series = [];
+							for (var r = 0; r < resp.length; r += 1) {
+								var rs = resp[r][1];
+								if (rs.length > 0) {
+									series.push(rs);
+								}
+							}
+							$scope.metricList[chartname] = mergeSeries(chartname, series, chart.metrics, chart.option);
+						});
 					});
 				});
 
@@ -146,7 +268,7 @@
 				var series = [];
 				$.each(metrics, function (i, metricMap) {
 					$.map(metricMap, function (metric) {
-						if(typeof metric !== 'undefined') {
+						if (typeof metric !== 'undefined') {
 							series.push(METRIC.metricsToSeries(linename[i], metric, option));
 						}
 					});
@@ -154,7 +276,8 @@
 				return {
 					title: title,
 					series: series,
-					option: option || {}
+					option: option || {},
+					loading: false
 				};
 			}
 		});

http://git-wip-us.apache.org/repos/asf/eagle/blob/1cfff2b9/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 5e3d00c..73912b8 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
@@ -85,13 +85,14 @@
 	</div>
 	<div class="box-body no-padding">
 		<div class="row border-split">
-			<div class="col-sm-6 col-md-4 col-lg-3" ng-repeat="metric in metricList track by $index">
+			<div class="col-sm-6 col-md-4 col-lg-3" ng-repeat="chart in chartList track by $index">
 				<div class="hadoopMetric-chart">
-					<h3>{{metric.title}}</h3>
-					<div ng-show="metric.series.length" chart class="hadoopMetric-chart-container"
-						 series="metric.series"
-						 option="metric.option"></div>
-					<div ng-show="!metric.series.length" class="hadoopMetric-chart-container">
+					<h3>{{metricList[chart.name].title}}</h3>
+					<div ng-show="metricList[chart.name].loading" class="fa fa-refresh fa-spin no-animate"></div>
+					<div ng-show="metricList[chart.name].series.length" chart class="hadoopMetric-chart-container"
+						 series="metricList[chart.name].series"
+						 option="metricList[chart.name].option"></div>
+					<div ng-show="!metricList[chart.name].series.length && !metricList[chart.name].loading" class="hadoopMetric-chart-container">
 						<div class="hadoopMetric-chart-container-withborder">
 							<div class="hadoopMetric-no-chart-data">
 								<span class="fa fa-question-circle"></span><span> NO DATA</span>
@@ -103,4 +104,3 @@
 		</div>
 	</div>
 </div>
-</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/1cfff2b9/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
index 441d0b8..2a5bff4 100644
--- 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
@@ -93,13 +93,14 @@
 	</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="col-sm-6 hadoopMetric-col-md-6 col-lg-3" ng-repeat="chart in chartList track by $index">
 				<div class="hadoopMetric-chart">
-					<h3>{{metric.title}}</h3>
-					<div ng-show="metric.series.length" chart class="hadoopMetric-chart-container"
-						 series="metric.series"
-						 option="metric.option"></div>
-					<div ng-show="!metric.series.length" class="hadoopMetric-chart-container">
+					<h3>{{metricList[chart.name].title}}</h3>
+					<div ng-show="metricList[chart.name].loading" class="fa fa-refresh fa-spin no-animate"></div>
+					<div ng-show="metricList[chart.name].series.length" chart class="hadoopMetric-chart-container"
+						 series="metricList[chart.name].series"
+						 option="metricList[chart.name].option"></div>
+					<div ng-show="!metricList[chart.name].series.length && !metricList[chart.name].loading" class="hadoopMetric-chart-container">
 						<div class="hadoopMetric-no-chart-data">
 							<span class="fa fa-question-circle"></span><span> NO DATA</span>
 						</div>
@@ -109,4 +110,3 @@
 		</div>
 	</div>
 </div>
-</div>

http://git-wip-us.apache.org/repos/asf/eagle/blob/1cfff2b9/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 9e73c9b..69c39e6 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
@@ -24,7 +24,7 @@
 		var COLOR_MAPPING = {
 			HDFS: 'orange',
 			HBase: 'yellow',
-			Yarn: 'green',
+			Yarn: 'green'
 		};
 
 		hadoopMetricApp.directive("hadoopMetricWidget", function () {
@@ -39,13 +39,13 @@
 						$scope.list = $.map(Application.find("HADOOP_METRIC_MONITOR"), function (app) {
 							return {
 								siteId: app.site.siteId,
-								siteName: app.site.siteName || app.site.siteId,
+								siteName: app.site.siteName || app.site.siteId
 							};
 						});
 					} else {
 						$scope.list = [{
 							siteId: site.siteId,
-							siteName: site.siteName || site.siteId,
+							siteName: site.siteName || site.siteId
 						}];
 					}
 					// Get type
@@ -75,7 +75,7 @@
 							});
 							countHBaseRole(site.siteId, "standby", "hmaster", ["site"], "count")._promise.then(function (res) {
 								$.map(res, function (data) {
-									$scope.hmasterstandbynum = data.value[0]
+									$scope.hmasterstandbynum = data.value[0];
 								});
 							});
 							countHBaseRole(site.siteId, "live", "regionserver", ["site"], "count")._promise.then(function (res) {