You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2015/10/28 18:46:09 UTC

[2/2] ambari git commit: AMBARI-13609. Incorrect metrics names in exported CSV file for Kafka

AMBARI-13609. Incorrect metrics names in exported CSV file for Kafka


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

Branch: refs/heads/branch-2.1
Commit: d6a54ace8ab0ed5e4869a5e9bbde5f5f43592750
Parents: 6432f63
Author: Alex Antonenko <hi...@gmail.com>
Authored: Wed Oct 28 19:45:06 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Wed Oct 28 19:45:59 2015 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   7 -
 ambari-web/app/messages.js                      |   4 +-
 .../mixins/common/chart/storm_linear_time.js    |  17 +-
 .../common/widgets/export_metrics_mixin.js      |  73 +++-----
 .../app/views/common/chart/linear_time.js       | 152 +++++++++++++---
 .../views/common/widget/graph_widget_view.js    |   4 +-
 .../views/main/dashboard/cluster_metrics/cpu.js |  31 ++--
 .../main/dashboard/cluster_metrics/load.js      |  15 +-
 .../main/dashboard/cluster_metrics/memory.js    |  20 +--
 .../main/dashboard/cluster_metrics/network.js   |  15 +-
 .../dashboard/widgets/cluster_metrics_widget.js |  18 +-
 ambari-web/app/views/main/host/metrics/cpu.js   |  69 ++++----
 ambari-web/app/views/main/host/metrics/disk.js  |  45 ++---
 ambari-web/app/views/main/host/metrics/load.js  |  33 +---
 .../app/views/main/host/metrics/memory.js       |  49 ++----
 .../app/views/main/host/metrics/network.js      |  37 ++--
 .../app/views/main/host/metrics/processes.js    |  29 +---
 .../ambari_metrics/master_average_load.js       |  25 +--
 .../metrics/ambari_metrics/regionserver_base.js |  27 +--
 .../info/metrics/flume/channel_fill_pct.js      |  32 ++--
 .../service/info/metrics/flume/channel_size.js  |  32 ++--
 .../info/metrics/flume/channel_size_mma.js      |  18 +-
 .../service/info/metrics/flume/channel_sum.js   |  12 +-
 .../main/service/info/metrics/flume/cpu_user.js |  27 +--
 .../info/metrics/flume/flume_incoming_mma.js    |  18 +-
 .../info/metrics/flume/flume_incoming_sum.js    |  12 +-
 .../info/metrics/flume/flume_metric_graph.js    |  27 +--
 .../info/metrics/flume/flume_outgoing_mma.js    |  18 +-
 .../info/metrics/flume/flume_outgoing_sum.js    |  12 +-
 .../views/main/service/info/metrics/flume/gc.js |  27 +--
 .../main/service/info/metrics/flume/jvm_heap.js |  35 ++--
 .../info/metrics/flume/jvm_threads_runnable.js  |  29 +---
 .../metrics/flume/sink_connection_failed.js     |  32 ++--
 .../info/metrics/flume/sink_drain_success.js    |  32 ++--
 .../info/metrics/flume/source_accepted.js       |  32 ++--
 .../service/info/metrics/kafka/broker_topic.js  |  37 ++--
 .../info/metrics/kafka/controller_status.js     |  33 ++--
 .../info/metrics/kafka/kafka_controller.js      |  11 +-
 .../info/metrics/kafka/replica_fetcher.js       |  11 +-
 .../info/metrics/kafka/replica_manager.js       |  33 +---
 .../common/chart/storm_linear_time_test.js      |  11 +-
 .../common/widgets/export_metrics_mixin_test.js | 173 ++++++++-----------
 .../common/widget/graph_widget_view_test.js     |  35 ++--
 .../dashboard/cluster_metrics/memory_test.js    |  80 ---------
 .../widgets/cluster_metrics_widget_test.js      |  56 ++----
 .../info/metrics/flume/channel_size_mma_test.js | 142 ---------------
 .../info/metrics/flume/channel_sum_test.js      | 108 ------------
 .../metrics/flume/flume_incoming_mma_test.js    | 142 ---------------
 .../metrics/flume/flume_incoming_sum_test.js    | 108 ------------
 .../metrics/flume/flume_outgoing_mma_test.js    | 142 ---------------
 .../metrics/flume/flume_outgoing_sum_test.js    | 108 ------------
 51 files changed, 573 insertions(+), 1722 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 78cad87..09b782b 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -224,7 +224,6 @@ var files = ['test/init_model_test',
   'test/views/main/dashboard/config_history_view_test',
   'test/views/main/dashboard/widget_test',
   'test/views/main/dashboard/widgets_test',
-  'test/views/main/dashboard/cluster_metrics/memory_test',
   'test/views/main/dashboard/widgets/text_widget_test',
   'test/views/main/dashboard/widgets/uptime_text_widget_test',
   'test/views/main/dashboard/widgets/node_managers_live_test',
@@ -256,12 +255,6 @@ var files = ['test/init_model_test',
   'test/views/main/service/info/config_test',
   'test/views/main/service/info/summary_test',
   'test/views/main/service/info/metrics/ambari_metrics/regionserver_base_test',
-  'test/views/main/service/info/metrics/flume/channel_size_mma_test',
-  'test/views/main/service/info/metrics/flume/channel_sum_test',
-  'test/views/main/service/info/metrics/flume/flume_incoming_mma_test',
-  'test/views/main/service/info/metrics/flume/flume_incoming_sum_test',
-  'test/views/main/service/info/metrics/flume/flume_outgoing_mma_test',
-  'test/views/main/service/info/metrics/flume/flume_outgoing_sum_test',
   'test/views/main/service/services/ranger_test',
   'test/views/main/service/widgets/create/expression_view_test',
   'test/views/main/admin/highAvailability/nameNode/step1_view_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 2aa9d1a..0ce69ad 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1805,8 +1805,8 @@ Em.I18n.translations = {
   'services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsBytesInPerSec': 'Bytes In',
   'services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsMessagesInPerSec': 'Messages In',
   'services.service.info.metrics.kafka.server.ReplicaManager.title': 'Replica Manager',
-  'services.service.info.metrics.kafka.server.ReplicaManager.displayNames.PartitionCount': 'Partiotions count',
-  'services.service.info.metrics.kafka.server.ReplicaManager.displayNames.UnderReplicatedPartitions': 'Under Replicated Partiotions',
+  'services.service.info.metrics.kafka.server.ReplicaManager.displayNames.PartitionCount': 'Partitions count',
+  'services.service.info.metrics.kafka.server.ReplicaManager.displayNames.UnderReplicatedPartitions': 'Under Replicated Partitions',
   'services.service.info.metrics.kafka.server.ReplicaManager.displayNames.LeaderCount': 'Leader Count',
   'services.service.info.metrics.kafka.controller.ControllerStats.title': 'Controller Status',
   'services.service.info.metrics.kafka.controller.ControllerStats.displayNames.LeaderElectionRateAndTimeMs': 'Leader Election Rate And Time',

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/mixins/common/chart/storm_linear_time.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/chart/storm_linear_time.js b/ambari-web/app/mixins/common/chart/storm_linear_time.js
index f70db0b..62a606d 100644
--- a/ambari-web/app/mixins/common/chart/storm_linear_time.js
+++ b/ambari-web/app/mixins/common/chart/storm_linear_time.js
@@ -36,10 +36,10 @@ App.StormLinearTimeChartMixin = Em.Mixin.create({
     };
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var pathKeys = ['metrics','storm','nimbus'];
-    var validPath = true;
+  getData: function (jsonData) {
+    var dataArray = [],
+      pathKeys = ['metrics','storm','nimbus'],
+      validPath = true;
     pathKeys.forEach(function(key) {
       if (!jsonData[key]) {
         validPath = false;
@@ -48,11 +48,14 @@ App.StormLinearTimeChartMixin = Em.Mixin.create({
       }
     });
     if (!validPath) {
-      return seriesArray;
+      return dataArray;
     }
     this.get('stormChartDefinition').forEach(function(chart){
-      seriesArray.push(this.transformData(jsonData[chart.field], chart.name));
+      dataArray.push({
+        name: chart.name,
+        data: jsonData[chart.field]
+      });
     }, this);
-    return seriesArray;
+    return dataArray;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/mixins/common/widgets/export_metrics_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/widgets/export_metrics_mixin.js b/ambari-web/app/mixins/common/widgets/export_metrics_mixin.js
index 1f2d657..84a2194 100644
--- a/ambari-web/app/mixins/common/widgets/export_metrics_mixin.js
+++ b/ambari-web/app/mixins/common/widgets/export_metrics_mixin.js
@@ -35,6 +35,10 @@ App.ExportMetricsMixin = Em.Mixin.create({
 
   exportMetricsMenuView: App.ExportMetricsMenuView.extend(),
 
+  targetView: function () {
+    return this.get('exportTargetView') || this;
+  }.property(),
+
   hideMenuForNoData: function () {
     if (this.get('isExportButtonHidden')) {
       this.set('isExportMenuHidden', true);
@@ -45,18 +49,28 @@ App.ExportMetricsMixin = Em.Mixin.create({
     this.toggleProperty('isExportMenuHidden');
   },
 
-  exportGraphData: function () {
+  exportGraphData: function (event) {
     this.set('isExportMenuHidden', true);
+    var ajaxIndex = this.get('targetView.ajaxIndex');
+    App.ajax.send({
+      name: ajaxIndex,
+      data: $.extend(this.get('targetView').getDataForAjaxRequest(), {
+        isCSV: !!event.context
+      }),
+      sender: this,
+      success: 'exportGraphDataSuccessCallback',
+      error: 'exportGraphDataErrorCallback'
+    });
   },
 
   exportGraphDataSuccessCallback: function (response, request, params) {
-    var hasData = response && response.metrics && Em.keys(response.metrics).length;
-    if (!hasData) {
+    var seriesData = this.get('targetView').getData(response);
+    if (!seriesData.length) {
       App.showAlertPopup(Em.I18n.t('graphs.noData.title'), Em.I18n.t('graphs.noData.tooltip.title'));
     } else {
       var fileType = params.isCSV ? 'csv' : 'json',
         fileName = 'data.' + fileType,
-        data = params.isCSV ? this.prepareCSV(response) : this.prepareJSON(response);
+        data = params.isCSV ? this.prepareCSV(seriesData) : JSON.stringify(seriesData, null, 4);
       fileUtils.downloadTextFile(data, fileType, fileName);
     }
   },
@@ -65,45 +79,12 @@ App.ExportMetricsMixin = Em.Mixin.create({
     App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.method, jqXHR.status);
   },
 
-  /**
-   * Take metrics from any depth level in JSON response
-   * @method setMetricsArrays
-   * @param data
-   * @param metrics
-   * @param titles
-   */
-  setMetricsArrays: function (data, metrics, titles) {
-    Em.keys(data).forEach(function (key) {
-      if (Em.isArray(data[key])) {
-        titles.push(key);
-        metrics.push(data[key]);
-      } else {
-        this.setMetricsArrays(data[key], metrics, titles);
-      }
-    }, this);
-  },
-
   prepareCSV: function (data) {
-    var metrics = [],
-      getMetricsItem = function (i, j, k) {
-        var item;
-        if (data.metrics) {
-          item = metrics[j][i][k];
-        } else if (Em.isArray(data)) {
-          item = data[j].data[i][k];
-        }
-        return item;
-      },
-      titles,
+    var titles,
       ticksNumber,
       metricsNumber,
       metricsArray;
-    if (data.metrics) {
-      titles = [Em.I18n.t('common.timestamp')];
-      this.setMetricsArrays(data.metrics, metrics, titles);
-      ticksNumber = metrics[0].length;
-      metricsNumber = metrics.length
-    } else if (Em.isArray(data)) {
+    if (Em.isArray(data)) {
       titles = data.mapProperty('name');
       titles.unshift(Em.I18n.t('common.timestamp'));
       ticksNumber = data[0].data.length;
@@ -111,22 +92,12 @@ App.ExportMetricsMixin = Em.Mixin.create({
     }
     metricsArray = [titles];
     for (var i = 0; i < ticksNumber; i++) {
-      metricsArray.push([getMetricsItem(i, 0, 1)]);
+      metricsArray.push([data[0].data[i][1]]);
       for (var j = 0; j < metricsNumber; j++) {
-        metricsArray[i + 1].push(getMetricsItem(i, j, 0));
+        metricsArray[i + 1].push(data[j].data[i][0]);
       };
     }
     return stringUtils.arrayToCSV(metricsArray);
-  },
-
-  prepareJSON: function (data) {
-    var fileData;
-    if (data.metrics) {
-      fileData = JSON.stringify(data.metrics, null, 4);
-    } else if (Em.isArray(data)) {
-      fileData = JSON.stringify(data, ['name', 'data'], 4);
-    }
-    return fileData;
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/common/chart/linear_time.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/chart/linear_time.js b/ambari-web/app/views/common/chart/linear_time.js
index ccf26ac..24ca450 100644
--- a/ambari-web/app/views/common/chart/linear_time.js
+++ b/ambari-web/app/views/common/chart/linear_time.js
@@ -34,12 +34,13 @@ var dateUtils = require('utils/date/date');
  * <li>url - from where the data can be retrieved
  * <li>title - Title to be displayed when showing the chart
  * <li>id - which uniquely identifies this chart in any page
- * <li>#transformToSeries(jsonData) - function to map server data into graph
- * series
+ * <li>seriesTemplate - template used by getData method to process server data
  * </ul>
  *
  * Extending classes could optionally override the following:
  * <ul>
+ * <li>#getData(jsonData) - function to map server data into series format
+ * ready for export to graph and JSON formats
  * <li>#colorForSeries(series) - function to get custom colors per series
  * </ul>
  *
@@ -152,6 +153,20 @@ App.ChartLinearTimeView = Ember.View.extend(App.ExportMetricsMixin, {
    */
   displayUnit: null,
 
+  /**
+   * Object containing information to get metrics data from API response
+   * Supported properties:
+   * <ul>
+   * <li>path - exact path to metrics data in response JSON (required)
+   * <li>displayName(name, hostName) - returns display name for metrics
+   * depending on property name in response JSON and host name for Flume Agents
+   * <li>factor - number that metrics values should be multiplied by
+   * <li>flumePropertyName - property name to access certain Flume metrics
+   * </ul>
+   * @type {Object}
+   */
+  seriesTemplate: null,
+
   _containerSelector: function () {
     return '#' + this.get('id') + '-container';
   }.property('id'),
@@ -173,6 +188,113 @@ App.ChartLinearTimeView = Ember.View.extend(App.ExportMetricsMixin, {
     });
   },
 
+  /**
+   * Maps server data into series format ready for export to graph and JSON formats
+   * @param jsonData
+   * @returns {Array}
+   */
+  getData: function (jsonData) {
+    var dataArray = [],
+      template = this.get('seriesTemplate'),
+      data = Em.get(jsonData, template.path);
+    if (data) {
+      for (var name in data) {
+        var currentData = data[name];
+        if (currentData) {
+          var factor = template.factor,
+            displayName = template.displayName ? template.displayName(name) : name;
+          if (!Em.isNone(factor)) {
+            var dataLength = currentData.length;
+            for (var i = dataLength; i--;) {
+              currentData[i][0] *= factor;
+            }
+          }
+          dataArray.push({
+            name: displayName,
+            data: currentData
+          });
+        }
+      }
+    }
+    return dataArray;
+  },
+
+  /**
+   * Maps server data for certain Flume metrics into series format ready for export
+   * to graph and JSON formats
+   * @param jsonData
+   * @returns {Array}
+   */
+  getFlumeData: function (jsonData) {
+    var dataArray = [];
+    if (jsonData && jsonData.host_components) {
+      jsonData.host_components.forEach(function (hc) {
+        var hostName = hc.HostRoles.host_name,
+          host = App.Host.find(hostName),
+          template = this.get('template'),
+          data = Em.get(hc, template.path);
+        if (host && host.get('publicHostName')) {
+          hostName = host.get('publicHostName');
+        }
+        if (data) {
+          for (var cname in data) {
+            var seriesName = template.displayName ? template.displayName(cname, hostName) : cname,
+              seriesData = template.flumePropertyName ? data[cname][template.flumePropertyName] : data[cname];
+            if (seriesData) {
+              var factor = template.factor;
+              if (!Em.isNone(factor)) {
+                var dataLength = seriesData.length;
+                for (var i = dataLength; i--;) {
+                  seriesData[i][0] *= factor;
+                }
+              }
+              dataArray.push({
+                name: seriesName,
+                data: seriesData
+              });
+            }
+          }
+        }
+      }, this);
+    }
+    return dataArray;
+  },
+
+  /**
+   * Maps server data for Kafka Broker Topic and Controller Status metrics
+   * into series format ready for export to graph and JSON formats
+   * @param jsonData
+   * @returns {Array}
+   */
+  getKafkaData: function (jsonData) {
+    var dataArray = [],
+      template = this.get('seriesTemplate'),
+      data = Em.get(jsonData, template.path);
+    for (var name in data) {
+      var displayName = template.displayName(name);
+      dataArray.push({
+        name: displayName,
+        data: Em.get(data, name + '.1MinuteRate')
+      });
+    }
+    return dataArray;
+  },
+
+  /**
+   * Function to map data into graph series
+   * @param jsonData
+   * @returns {Array}
+   */
+  transformToSeries: function (jsonData) {
+    var seriesArray = [],
+      seriesData = this.getData(jsonData),
+      dataLength = seriesData.length;
+    for (var i = 0; i < dataLength; i++) {
+      seriesArray.push(this.transformData(seriesData[i].data, seriesData[i].name));
+    }
+    return seriesArray;
+  },
+
   setExportTooltip: function () {
     if (this.get('isReady')) {
       Em.run.next(this, function () {
@@ -819,13 +941,12 @@ App.ChartLinearTimeView = Ember.View.extend(App.ExportMetricsMixin, {
         }.property('isReady', 'parentView.currentTimeIndex'),
 
         exportGraphData: function (event) {
-          this._super();
+          this.set('isExportMenuHidden', true);
           var ajaxIndex = this.get('parentView.graph.ajaxIndex'),
-            isCSV = !!event.context,
             targetView = ajaxIndex ? this.get('parentView.graph') : self.get('parentView');
-            targetView.exportGraphData({
-              context: event.context
-            });
+          targetView.exportGraphData({
+            context: event.context
+          });
         }
       }),
       header: this.get('title'),
@@ -910,21 +1031,8 @@ App.ChartLinearTimeView = Ember.View.extend(App.ExportMetricsMixin, {
   }.observes('parentView.parentView.currentTimeRangeIndex', 'parentView.currentTimeRangeIndex'),
   timeUnitSeconds: function () {
     return this.get('timeStates').objectAt(this.get('currentTimeIndex')).seconds;
-  }.property('currentTimeIndex'),
-
-  exportGraphData: function (event) {
-    this._super();
-    var ajaxIndex = this.get('ajaxIndex');
-    App.ajax.send({
-      name: ajaxIndex,
-      data: $.extend(this.getDataForAjaxRequest(), {
-        isCSV: !!event.context
-      }),
-      sender: this,
-      success: 'exportGraphDataSuccessCallback',
-      error: 'exportGraphDataErrorCallback'
-    });
-  }
+  }.property('currentTimeIndex')
+
 });
 
 /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/common/widget/graph_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/widget/graph_widget_view.js b/ambari-web/app/views/common/widget/graph_widget_view.js
index 1ed20d2..62bf4d5 100644
--- a/ambari-web/app/views/common/widget/graph_widget_view.js
+++ b/ambari-web/app/views/common/widget/graph_widget_view.js
@@ -308,7 +308,7 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, App.ExportMetricsMixin, {
   }),
 
   exportGraphData: function (event) {
-    this._super();
+    this.set('isExportMenuHidden', true);
     var data,
       isCSV = !!event.context,
       fileType = isCSV ? 'csv' : 'json',
@@ -318,7 +318,7 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, App.ExportMetricsMixin, {
         return Em.isArray(item.data);
       });
     if (hasData) {
-      data = isCSV ? this.prepareCSV(metrics) : this.prepareJSON(metrics);
+      data = isCSV ? this.prepareCSV(metrics) : JSON.stringify(metrics, ['name', 'data'], 4);
       fileUtils.downloadTextFile(data, fileType, fileName);
     } else {
       App.showAlertPopup(Em.I18n.t('graphs.noData.title'), Em.I18n.t('graphs.noData.tooltip.title'));

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js b/ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
index 73b8f57..e959ca7 100644
--- a/ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
+++ b/ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
@@ -34,30 +34,37 @@ App.ChartClusterMetricsCPU = App.ChartLinearTimeView.extend({
   title: Em.I18n.t('dashboard.clusterMetrics.cpu'),
   yAxisFormatter: App.ChartLinearTimeView.PercentageFormatter,
   isTimePagingDisable: false,
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var idle = null;
+  seriesTemplate: {
+    path: 'metrics.cpu'
+  },
 
-    if (jsonData && jsonData.metrics && jsonData.metrics.cpu) {
-      for (var name in jsonData.metrics.cpu) {
-        var seriesData = jsonData.metrics.cpu[name];
+  getData: function (jsonData) {
+    var dataArray = [],
+      idle = null,
+      data = Em.get(jsonData, this.get('seriesTemplate.path'));
+    if (data) {
+      for (var name in data) {
+        var seriesData = data[name];
         if (seriesData) {
-          var s = this.transformData(seriesData, name);
-          if (name.indexOf("Idle") > -1) {
+          var s = {
+            name: name,
+            data: seriesData
+          };
+          if (name.indexOf('Idle') > -1) {
             //CPU idle metric should be the last in series array
             idle = s;
             continue;
           }
-          seriesArray.push(s);
+          dataArray.push(s);
         }
       }
       if (idle) {
-        seriesArray.push(idle);
+        dataArray.push(idle);
       }
     }
-    return seriesArray;
+    return dataArray;
   },
-  
+
   colorForSeries: function (series) {
     if (Em.I18n.t('dashboard.clusterMetrics.cpu.displayNames.idle') == series.name){
       return '#CFECEC';

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/dashboard/cluster_metrics/load.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/cluster_metrics/load.js b/ambari-web/app/views/main/dashboard/cluster_metrics/load.js
index 7e06b2c..eb4f2ca 100644
--- a/ambari-web/app/views/main/dashboard/cluster_metrics/load.js
+++ b/ambari-web/app/views/main/dashboard/cluster_metrics/load.js
@@ -34,18 +34,7 @@ App.ChartClusterMetricsLoad = App.ChartLinearTimeView.extend({
   isTimePagingDisable: false,
   renderer: 'line',
   title: Em.I18n.t('dashboard.clusterMetrics.load'),
-  
-  transformToSeries: function(jsonData){
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.load) {
-      for ( var name in jsonData.metrics.load) {
-        var displayName = name;
-        var seriesData = jsonData.metrics.load[name];
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.load'
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/dashboard/cluster_metrics/memory.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/cluster_metrics/memory.js b/ambari-web/app/views/main/dashboard/cluster_metrics/memory.js
index db1988e..3bcdfb3 100644
--- a/ambari-web/app/views/main/dashboard/cluster_metrics/memory.js
+++ b/ambari-web/app/views/main/dashboard/cluster_metrics/memory.js
@@ -35,22 +35,8 @@ App.ChartClusterMetricsMemory = App.ChartLinearTimeView.extend({
   title: Em.I18n.t('dashboard.clusterMetrics.memory'),
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.memory) {
-      var KB = Math.pow(2, 10);
-      for ( var name in jsonData.metrics.memory) {
-        var displayName = name;
-        var seriesData = jsonData.metrics.memory[name];
-        if (seriesData) {
-          var s = this.transformData(seriesData, displayName);
-          for (var i = 0; i < s.data.length; i++) {
-            s.data[i].y *= KB;
-          }
-          seriesArray.push(s);
-        }
-      }
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.memory',
+    factor: Math.pow(2, 10)
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/dashboard/cluster_metrics/network.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/cluster_metrics/network.js b/ambari-web/app/views/main/dashboard/cluster_metrics/network.js
index 8c8fe77..3323bf1 100644
--- a/ambari-web/app/views/main/dashboard/cluster_metrics/network.js
+++ b/ambari-web/app/views/main/dashboard/cluster_metrics/network.js
@@ -36,18 +36,7 @@ App.ChartClusterMetricsNetwork = App.ChartLinearTimeView.extend({
   title: Em.I18n.t('dashboard.clusterMetrics.network'),
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
-
-  transformToSeries : function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.network) {
-      for ( var name in jsonData.metrics.network) {
-        var displayName = name;
-        var seriesData = jsonData.metrics.network[name];
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.network'
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js b/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
index a4dfd69..9704ae2 100644
--- a/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
+++ b/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
@@ -22,6 +22,10 @@ App.ClusterMetricsDashboardWidgetView = App.DashboardWidgetView.extend(App.Expor
 
   templateName: require('templates/main/dashboard/widgets/cluster_metrics'),
 
+  exportTargetView: function () {
+    return this.get('childViews.lastObject');
+  }.property(),
+
   didInsertElement: function () {
     var self = this;
     this.$().on('mouseleave', function () {
@@ -30,20 +34,6 @@ App.ClusterMetricsDashboardWidgetView = App.DashboardWidgetView.extend(App.Expor
     App.tooltip(this.$('.corner-icon > .icon-save'), {
       title: Em.I18n.t('common.export')
     });
-  },
-
-  exportGraphData: function (event) {
-    this._super();
-    var ajaxIndex = this.get('childViews.lastObject.ajaxIndex');
-    App.ajax.send({
-      name: ajaxIndex,
-      data: $.extend(this.get('childViews.lastObject').getDataForAjaxRequest(), {
-        isCSV: !!event.context
-      }),
-      sender: this,
-      success: 'exportGraphDataSuccessCallback',
-      error: 'exportGraphDataErrorCallback'
-    });
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/cpu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/cpu.js b/ambari-web/app/views/main/host/metrics/cpu.js
index 45cd4d5..8cbdb15 100644
--- a/ambari-web/app/views/main/host/metrics/cpu.js
+++ b/ambari-web/app/views/main/host/metrics/cpu.js
@@ -38,48 +38,45 @@ App.ChartHostMetricsCPU = App.ChartLinearTimeView.extend({
     fields: ['metrics/cpu/cpu_user', 'metrics/cpu/cpu_wio', 'metrics/cpu/cpu_nice', 'metrics/cpu/cpu_aidle', 'metrics/cpu/cpu_system', 'metrics/cpu/cpu_idle']
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.cpu) {
-      var cpu_idle;
-      for ( var name in jsonData.metrics.cpu) {
-        var displayName;
-        var seriesData = jsonData.metrics.cpu[name];
-        switch (name) {
-          case "cpu_wio":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_wio');
-            break;
-          case "cpu_idle":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_idle');
-            break;
-          case "cpu_nice":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_nice');
-            break;
-          case "cpu_aidle":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_aidle');
-            break;
-          case "cpu_system":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_system');
-            break;
-          case "cpu_user":
-            displayName = Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_user');
-            break;
-          default:
-            break;
-        }
+  seriesTemplate: {
+    path: 'metrics.cpu',
+    displayName: function (name) {
+      var displayNameMap = {
+        cpu_wio: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_wio'),
+        cpu_idle: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_idle'),
+        cpu_nice: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_nice'),
+        cpu_aidle: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_aidle'),
+        cpu_system: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_system'),
+        cpu_user: Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_user')
+      };
+      return displayNameMap[name];
+    }
+  },
+
+  getData: function (jsonData) {
+    var dataArray = [],
+      cpu_idle,
+      template = this.get('seriesTemplate'),
+      data = Em.get(jsonData, template.path);
+    if (data) {
+      for (var name in data) {
+        var displayName = template.displayName(name),
+          seriesData = data[name];
         if (seriesData) {
-          var s = this.transformData(seriesData, displayName);
-          if (Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_idle') == s.name) {
+          var s = {
+            name: displayName,
+            data: seriesData
+          };
+          if (Em.I18n.t('hosts.host.metrics.cpu.displayNames.cpu_idle') == displayName) {
             cpu_idle = s;
-          }
-          else {
-            seriesArray.push(s);
+          } else {
+            dataArray.push(s);
           }
         }
       }
-      seriesArray.push(cpu_idle);
+      dataArray.push(cpu_idle);
     }
-    return seriesArray;
+    return dataArray;
   },
 
   colorForSeries: function (series) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/disk.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/disk.js b/ambari-web/app/views/main/host/metrics/disk.js
index 447fbd8..d05b65f 100644
--- a/ambari-web/app/views/main/host/metrics/disk.js
+++ b/ambari-web/app/views/main/host/metrics/disk.js
@@ -39,35 +39,22 @@ App.ChartHostMetricsDisk = App.ChartLinearTimeView.extend({
     fields: ['metrics/disk/disk_total', 'metrics/disk/disk_free']
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var GB = Math.pow(2, 30);
-    if (jsonData && jsonData.metrics && jsonData.metrics.disk) {
-      if(jsonData.metrics.part_max_used){
-        jsonData.metrics.disk.part_max_used = jsonData.metrics.part_max_used;
-      }
-      for ( var name in jsonData.metrics.disk) {
-        var displayName;
-        var seriesData = jsonData.metrics.disk[name];
-        switch (name) {
-          case "disk_total":
-            displayName = Em.I18n.t('hosts.host.metrics.disk.displayNames.disk_total');
-            break;
-          case "disk_free":
-            displayName = Em.I18n.t('hosts.host.metrics.disk.displayNames.disk_free');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          var s = this.transformData(seriesData, displayName);
-          for (var i = 0; i < s.data.length; i++) {
-            s.data[i].y *= GB;
-          }
-          seriesArray.push(s);
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.disk',
+    displayName: function (name) {
+      var displayNameMap = {
+        disk_total: Em.I18n.t('hosts.host.metrics.disk.displayNames.disk_total'),
+        disk_free: Em.I18n.t('hosts.host.metrics.disk.displayNames.disk_free')
+      };
+      return displayNameMap[name];
+    },
+    factor: Math.pow(2, 30)
+  },
+
+  getData: function (jsonData) {
+    if (jsonData.metrics.part_max_used) {
+      jsonData.metrics.disk.part_max_used = jsonData.metrics.part_max_used;
     }
-    return seriesArray;
+    return this._super(jsonData);
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/load.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/load.js b/ambari-web/app/views/main/host/metrics/load.js
index d5926fd..7a8df8c 100644
--- a/ambari-web/app/views/main/host/metrics/load.js
+++ b/ambari-web/app/views/main/host/metrics/load.js
@@ -38,30 +38,15 @@ App.ChartHostMetricsLoad = App.ChartLinearTimeView.extend({
     fields: ['metrics/load/load_fifteen', 'metrics/load/load_one', 'metrics/load/load_five']
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.load) {
-      for ( var name in jsonData.metrics.load) {
-        var displayName;
-        var seriesData = jsonData.metrics.load[name];
-        switch (name) {
-          case "load_fifteen":
-            displayName = Em.I18n.t('hosts.host.metrics.load.displayNames.load_fifteen');
-            break;
-          case "load_one":
-            displayName = Em.I18n.t('hosts.host.metrics.load.displayNames.load_one');
-            break;
-          case "load_five":
-            displayName = Em.I18n.t('hosts.host.metrics.load.displayNames.load_five');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.load',
+    displayName: function (name) {
+      var displayNameMap = {
+        load_fifteen: Em.I18n.t('hosts.host.metrics.load.displayNames.load_fifteen'),
+        load_one: Em.I18n.t('hosts.host.metrics.load.displayNames.load_one'),
+        load_five: Em.I18n.t('hosts.host.metrics.load.displayNames.load_five')
+      };
+      return displayNameMap[name]
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/memory.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/memory.js b/ambari-web/app/views/main/host/metrics/memory.js
index 200775e..93e6be9 100644
--- a/ambari-web/app/views/main/host/metrics/memory.js
+++ b/ambari-web/app/views/main/host/metrics/memory.js
@@ -45,41 +45,18 @@ App.ChartHostMetricsMemory = App.ChartLinearTimeView.extend({
     ]
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var KB = Math.pow(2, 10);
-    if (jsonData && jsonData.metrics && jsonData.metrics.memory) {
-      for ( var name in jsonData.metrics.memory) {
-        var displayName;
-        var seriesData = jsonData.metrics.memory[name];
-        switch (name) {
-          case "mem_shared":
-            displayName = Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_shared');
-            break;
-          case "swap_free":
-            displayName = Em.I18n.t('hosts.host.metrics.memory.displayNames.swap_free');
-            break;
-          case "mem_buffers":
-            displayName = Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_buffers');
-            break;
-          case "mem_free":
-            displayName = Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_free');
-            break;
-          case "mem_cached":
-            displayName = Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_cached');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          var s = this.transformData(seriesData, displayName);
-          for (var i = 0; i < s.data.length; i++) {
-            s.data[i].y *= KB;
-          }
-          seriesArray.push(s);
-        }
-      }
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.memory',
+    displayName: function (name) {
+      var displayNameMap = {
+        mem_shared: Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_shared'),
+        swap_free: Em.I18n.t('hosts.host.metrics.memory.displayNames.swap_free'),
+        mem_buffers: Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_buffers'),
+        mem_free: Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_free'),
+        mem_cached: Em.I18n.t('hosts.host.metrics.memory.displayNames.mem_cached')
+      };
+      return displayNameMap[name];
+    },
+    factor: Math.pow(2, 10)
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/network.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/network.js b/ambari-web/app/views/main/host/metrics/network.js
index 5f134a2..7b22481 100644
--- a/ambari-web/app/views/main/host/metrics/network.js
+++ b/ambari-web/app/views/main/host/metrics/network.js
@@ -44,33 +44,16 @@ App.ChartHostMetricsNetwork = App.ChartLinearTimeView.extend({
     ]
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.network) {
-      for ( var name in jsonData.metrics.network) {
-        var displayName;
-        var seriesData = jsonData.metrics.network[name];
-        switch (name) {
-          case "pkts_out":
-            displayName = Em.I18n.t('hosts.host.metrics.network.displayNames.pkts_out');
-            break;
-          case "bytes_in":
-            displayName = Em.I18n.t('hosts.host.metrics.network.displayNames.bytes_in');
-            break;
-          case "bytes_out":
-            displayName = Em.I18n.t('hosts.host.metrics.network.displayNames.bytes_out');
-            break;
-          case "pkts_in":
-            displayName = Em.I18n.t('hosts.host.metrics.network.displayNames.pkts_in');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.network',
+    displayName: function (name) {
+      var displayNameMap = {
+        pkts_out: Em.I18n.t('hosts.host.metrics.network.displayNames.pkts_out'),
+        bytes_in: Em.I18n.t('hosts.host.metrics.network.displayNames.bytes_in'),
+        bytes_out: Em.I18n.t('hosts.host.metrics.network.displayNames.bytes_out'),
+        pkts_in: Em.I18n.t('hosts.host.metrics.network.displayNames.pkts_in')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/host/metrics/processes.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/metrics/processes.js b/ambari-web/app/views/main/host/metrics/processes.js
index 5358e9e..4692789 100644
--- a/ambari-web/app/views/main/host/metrics/processes.js
+++ b/ambari-web/app/views/main/host/metrics/processes.js
@@ -38,27 +38,14 @@ App.ChartHostMetricsProcesses = App.ChartLinearTimeView.extend({
     fields: ['metrics/process/proc_total', 'metrics/process/proc_run']
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.process) {
-      for ( var name in jsonData.metrics.process) {
-        var displayName;
-        var seriesData = jsonData.metrics.process[name];
-        switch (name) {
-          case "proc_total":
-            displayName = Em.I18n.t('hosts.host.metrics.processes.displayNames.proc_total');
-            break;
-          case "proc_run":
-            displayName = Em.I18n.t('hosts.host.metrics.processes.displayNames.proc_run');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.process',
+    displayName: function (name) {
+      var displayNameMap = {
+        proc_total: Em.I18n.t('hosts.host.metrics.processes.displayNames.proc_total'),
+        proc_run: Em.I18n.t('hosts.host.metrics.processes.displayNames.proc_run')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/ambari_metrics/master_average_load.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/ambari_metrics/master_average_load.js b/ambari-web/app/views/main/service/info/metrics/ambari_metrics/master_average_load.js
index f381416..67b1b19 100644
--- a/ambari-web/app/views/main/service/info/metrics/ambari_metrics/master_average_load.js
+++ b/ambari-web/app/views/main/service/info/metrics/ambari_metrics/master_average_load.js
@@ -36,24 +36,13 @@ App.ChartServiceMetricsAMS_MasterAverageLoad = App.ChartLinearTimeView.extend({
     fields: ['metrics/hbase/master/AverageLoad']
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.hbase && jsonData.metrics.hbase.master) {
-      for ( var name in jsonData.metrics.hbase.master) {
-        var displayName;
-        var seriesData = jsonData.metrics.hbase.master[name];
-        switch (name) {
-          case "AverageLoad":
-            displayName = Em.I18n.t('services.service.info.metrics.ambariMetrics.master.displayNames.averageLoad');
-            break;
-          default:
-            break;
-        }
-        if (seriesData) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.hbase.master',
+    displayName: function (name) {
+      var displayNameMap = {
+        AverageLoad: Em.I18n.t('services.service.info.metrics.ambariMetrics.master.displayNames.averageLoad')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/ambari_metrics/regionserver_base.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/ambari_metrics/regionserver_base.js b/ambari-web/app/views/main/service/info/metrics/ambari_metrics/regionserver_base.js
index b28bd28..771b5e2 100644
--- a/ambari-web/app/views/main/service/info/metrics/ambari_metrics/regionserver_base.js
+++ b/ambari-web/app/views/main/service/info/metrics/ambari_metrics/regionserver_base.js
@@ -29,21 +29,28 @@ var App = require('app');
 App.ChartServiceMetricsAMS_RegionServerBaseView = App.ChartLinearTimeView.extend({
   displayName: '',
   regionServerName: '',
+  seriesTemplate: {
+    path: 'metrics.hbase.regionserver'
+  },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (jsonData && jsonData.metrics && jsonData.metrics.hbase && jsonData.metrics.hbase.regionserver) {
-      for (var name in jsonData.metrics.hbase.regionserver) {
-        var displayName,
-            seriesData = jsonData.metrics.hbase.regionserver[name];
+  getData: function (jsonData) {
+    var dataArray = [],
+      template = this.get('seriesTemplate'),
+      data = Em.get(jsonData, template.path);
+    if (data) {
+      for (var name in data) {
         if (name === this.get('regionServerName')) {
-          displayName = this.get('displayName');
-          if (seriesData) {
-            seriesArray.push(this.transformData(seriesData, displayName));
+          var displayName = this.get('displayName'),
+            currentData = data[name];
+          if (currentData) {
+            dataArray.push({
+              name: displayName,
+              data: currentData
+            });
           }
         }
       }
     }
-    return seriesArray;
+    return dataArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/channel_fill_pct.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/channel_fill_pct.js b/ambari-web/app/views/main/service/info/metrics/flume/channel_fill_pct.js
index c057636..524ec93 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/channel_fill_pct.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/channel_fill_pct.js
@@ -33,27 +33,15 @@ App.ChartServiceMetricsFlume_ChannelFillPercent = App.ChartLinearTimeView.extend
 
   ajaxIndex: 'service.metrics.flume.channel_fill_percent',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.flume && hc.metrics.flume.flume && hc.metrics.flume.flume.CHANNEL) {
-          for ( var cname in hc.metrics.flume.flume.CHANNEL) {
-            var seriesName = Em.I18n.t('services.service.info.metrics.flume.channelName').format(cname + " (" + hostName + ")");
-            var seriesData = hc.metrics.flume.flume.CHANNEL[cname]['ChannelFillPercentage'];
-            if (seriesData) {
-              seriesArray.push(self.transformData(seriesData, seriesName));
-            }
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.channelName').format(name + ' (' + hostName + ')');
+    },
+    flumePropertyName: 'ChannelFillPercentage'
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/channel_size.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/channel_size.js b/ambari-web/app/views/main/service/info/metrics/flume/channel_size.js
index 665b04a..71a7bf3 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/channel_size.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/channel_size.js
@@ -32,27 +32,15 @@ App.ChartServiceMetricsFlume_ChannelSize = App.ChartLinearTimeView.extend({
 
   ajaxIndex: 'service.metrics.flume.channel_size',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.flume && hc.metrics.flume.flume && hc.metrics.flume.flume.CHANNEL) {
-          for ( var cname in hc.metrics.flume.flume.CHANNEL) {
-            var seriesName = Em.I18n.t('services.service.info.metrics.flume.channelName').format(cname + " (" + hostName + ")");
-            var seriesData = hc.metrics.flume.flume.CHANNEL[cname]['ChannelSize'];
-            if (seriesData) {
-              seriesArray.push(self.transformData(seriesData, seriesName));
-            }
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.channelName').format(name + ' (' + hostName + ')');
+    },
+    flumePropertyName: 'ChannelSize'
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/channel_size_mma.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/channel_size_mma.js b/ambari-web/app/views/main/service/info/metrics/flume/channel_size_mma.js
index d4c1fe0..a5041bb 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/channel_size_mma.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/channel_size_mma.js
@@ -34,21 +34,11 @@ App.ChartServiceMetricsFlume_ChannelSizeMMA = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.CreateRateFormatter('',
     App.ChartLinearTimeView.DefaultFormatter),
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var data = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.ChannelSize.rate');
-
-    if (data) {
-      for (var cname in data) {
-        var seriesName = Em.I18n.t('services.service.info.metrics.flume.channelType').format(cname);
-        var seriesData = data[cname];
-        if (seriesData) {
-          seriesArray.push(self.transformData(seriesData, seriesName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.ChannelSize.rate',
+    displayName: function (name) {
+      return Em.I18n.t('services.service.info.metrics.flume.channelType').format(name);
     }
-    return seriesArray;
   },
 
   colorForSeries: function (series) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/channel_sum.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/channel_sum.js b/ambari-web/app/views/main/service/info/metrics/flume/channel_sum.js
index b102575..c978132 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/channel_sum.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/channel_sum.js
@@ -33,14 +33,10 @@ App.ChartServiceMetricsFlume_ChannelSizeSum = App.ChartLinearTimeView.extend({
 
   ajaxIndex: 'service.metrics.flume.channel_size_for_all.sum',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var seriesData = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.ChannelSize.rate.sum');
-    if (seriesData) {
-      var seriesName = Em.I18n.t('services.service.info.metrics.flume.channelSizeSum');
-      seriesArray.push(self.transformData(seriesData, seriesName));
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.ChannelSize.rate',
+    displayName: function () {
+      return Em.I18n.t('services.service.info.metrics.flume.channelSizeSum');
     }
-    return seriesArray;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/cpu_user.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/cpu_user.js b/ambari-web/app/views/main/service/info/metrics/flume/cpu_user.js
index e66b849..c5c08d9 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/cpu_user.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/cpu_user.js
@@ -34,25 +34,14 @@ App.ChartServiceMetricsFlume_CPUUser = App.ChartLinearTimeView.extend({
   
   ajaxIndex: 'service.metrics.flume.cpu_user',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.cpu && hc.metrics.cpu.cpu_user) {
-          var seriesName = Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
-          var seriesData = hc.metrics.cpu.cpu_user;
-          if (seriesData) {
-            seriesArray.push(self.transformData(seriesData, seriesName));
-          }
-        }
-      });
+  seriesTemplate: {
+    path: 'metrics.cpu.cpu_user',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
     }
-    return seriesArray;
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_mma.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_mma.js b/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_mma.js
index 48ee7f6..9d47a81 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_mma.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_mma.js
@@ -34,21 +34,11 @@ App.ChartServiceMetricsFlume_IncommingMMA = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.CreateRateFormatter('',
       App.ChartLinearTimeView.DefaultFormatter),
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var data = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.EventPutSuccessCount.rate');
-
-    if (data) {
-      for (var cname in data) {
-        var seriesName = Em.I18n.t('services.service.info.metrics.flume.incoming_mma').format(cname);
-        var seriesData = data[cname];
-        if (seriesData) {
-          seriesArray.push(self.transformData(seriesData, seriesName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.EventPutSuccessCount.rate',
+    displayName: function (name) {
+      return Em.I18n.t('services.service.info.metrics.flume.incoming_mma').format(name);
     }
-    return seriesArray;
   },
 
   colorForSeries: function (series) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_sum.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_sum.js b/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_sum.js
index 51a1287..9718d27 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_sum.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/flume_incoming_sum.js
@@ -31,14 +31,10 @@ App.ChartServiceMetricsFlume_IncommingSum = App.ChartLinearTimeView.extend({
 
   ajaxIndex: 'service.metrics.flume.incoming_event_put_successCount.sum',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var seriesData = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.EventPutSuccessCount.rate.sum');
-    if (seriesData) {
-      var seriesName = Em.I18n.t('services.service.info.metrics.flume.incoming.sum');
-      seriesArray.push(self.transformData(seriesData, seriesName));
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.EventPutSuccessCount.rate',
+    displayName: function () {
+      return Em.I18n.t('services.service.info.metrics.flume.incoming.sum');
     }
-    return seriesArray;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/flume_metric_graph.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/flume_metric_graph.js b/ambari-web/app/views/main/service/info/metrics/flume/flume_metric_graph.js
index f138f40..43a9b51 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/flume_metric_graph.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/flume_metric_graph.js
@@ -59,20 +59,25 @@ App.ChartServiceFlumeMetricGraph = App.ChartLinearTimeView.extend({
     return data;
   },
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.metrics && jsonData.metrics.flume && jsonData.metrics.flume.flume &&
-        jsonData.metrics.flume.flume[this.get('metricType')]) {
-      var metricTypeData = jsonData.metrics.flume.flume[this.get('metricType')];
-      for ( var componentName in metricTypeData) {
-        var seriesName = componentName;
-        var seriesData = metricTypeData[componentName][this.get('metricName')];
+  seriesTemplate: {
+    path: 'metrics.flume.flume'
+  },
+
+  getData: function (jsonData) {
+
+    var dataArray = [],
+      data = Em.get(jsonData, this.get('seriesTemplate.path') + '.' + this.get('metricType'));
+    if (data) {
+      for (var componentName in data) {
+        var seriesData = data[componentName][this.get('metricName')];
         if (seriesData) {
-          seriesArray.push(self.transformData(seriesData, seriesName));
+          dataArray.push({
+            name: componentName,
+            data: seriesData
+          });
         }
       }
     }
-    return seriesArray;
+    return dataArray;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_mma.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_mma.js b/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_mma.js
index ea1b947..1b07536 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_mma.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_mma.js
@@ -34,21 +34,11 @@ App.ChartServiceMetricsFlume_OutgoingMMA = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.CreateRateFormatter('',
       App.ChartLinearTimeView.DefaultFormatter),
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var data = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.EventTakeSuccessCount.rate');
-
-    if (data) {
-      for (var cname in data) {
-        var seriesName = Em.I18n.t('services.service.info.metrics.flume.outgoing_mma').format(cname);
-        var seriesData = data[cname];
-        if (seriesData) {
-          seriesArray.push(self.transformData(seriesData, seriesName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.EventTakeSuccessCount.rate',
+    displayName: function (name) {
+      return Em.I18n.t('services.service.info.metrics.flume.outgoing_mma').format(name);
     }
-    return seriesArray;
   },
 
   colorForSeries: function (series) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_sum.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_sum.js b/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_sum.js
index 8862f8c..3ce6b6e 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_sum.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/flume_outgoing_sum.js
@@ -31,14 +31,10 @@ App.ChartServiceMetricsFlume_OutgoingSum = App.ChartLinearTimeView.extend({
 
   ajaxIndex: 'service.metrics.flume.outgoing_event_take_success_count.sum',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var seriesData = Em.get(jsonData, 'metrics.flume.flume.CHANNEL.EventTakeSuccessCount.rate.sum');
-    if (seriesData) {
-      var seriesName = Em.I18n.t('services.service.info.metrics.flume.outgoing.sum');
-      seriesArray.push(self.transformData(seriesData, seriesName));
+  seriesTemplate: {
+    path: 'metrics.flume.flume.CHANNEL.EventTakeSuccessCount.rate',
+    displayName: function () {
+      return Em.I18n.t('services.service.info.metrics.flume.outgoing.sum');
     }
-    return seriesArray;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/gc.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/gc.js b/ambari-web/app/views/main/service/info/metrics/flume/gc.js
index 7842c81..ce2f035 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/gc.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/gc.js
@@ -33,25 +33,14 @@ App.ChartServiceMetricsFlume_GarbageCollection = App.ChartLinearTimeView.extend(
 
   ajaxIndex: 'service.metrics.flume.gc',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.jvm && hc.metrics.jvm.gcTimeMillis) {
-          var seriesName = Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
-          var seriesData = hc.metrics.jvm.gcTimeMillis;
-          if (seriesData) {
-            seriesArray.push(self.transformData(seriesData, seriesName));
-          }
-        }
-      });
+  seriesTemplate: {
+    path: 'metrics.jvm.gcTimeMillis',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
     }
-    return seriesArray;
+  },
+
+   getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/jvm_heap.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/jvm_heap.js b/ambari-web/app/views/main/service/info/metrics/flume/jvm_heap.js
index 0dc1cc4..10acf19 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/jvm_heap.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/jvm_heap.js
@@ -34,30 +34,15 @@ App.ChartServiceMetricsFlume_JVMHeapUsed = App.ChartLinearTimeView.extend({
 
   ajaxIndex: 'service.metrics.flume.jvm_heap_used',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var MB = Math.pow(2, 20);
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.jvm && hc.metrics.jvm.memHeapUsedM) {
-          var seriesName = Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
-          var seriesData = hc.metrics.jvm.memHeapUsedM;
-          if (seriesData) {
-            var s = self.transformData(seriesData, seriesName);
-            for (var i = 0; i < s.data.length; i++) {
-              s.data[i].y *= MB;
-            }
-            seriesArray.push(s);
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.jvm.memHeapUsedM',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
+    },
+    factor: Math.pow(2, 20)
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/jvm_threads_runnable.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/jvm_threads_runnable.js b/ambari-web/app/views/main/service/info/metrics/flume/jvm_threads_runnable.js
index 5f6840f..b2cfb06 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/jvm_threads_runnable.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/jvm_threads_runnable.js
@@ -33,27 +33,14 @@ App.ChartServiceMetricsFlume_JVMThreadsRunnable = App.ChartLinearTimeView.extend
 
   ajaxIndex: 'service.metrics.flume.jvm_threads_runnable',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    var MB = Math.pow(2, 20);
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.jvm && hc.metrics.jvm.threadsRunnable) {
-          var seriesName = Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
-          var seriesData = hc.metrics.jvm.threadsRunnable;
-          if (seriesData) {
-            var s = self.transformData(seriesData, seriesName);
-            seriesArray.push(s);
-          }
-        }
-      });
+  seriesTemplate: {
+    path: 'metrics.jvm.threadsRunnable',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.hostName').format(hostName);
     }
-    return seriesArray;
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/sink_connection_failed.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/sink_connection_failed.js b/ambari-web/app/views/main/service/info/metrics/flume/sink_connection_failed.js
index 1fdff4e..469a00c 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/sink_connection_failed.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/sink_connection_failed.js
@@ -32,27 +32,15 @@ App.ChartServiceMetricsFlume_SinkConnectionFailedCount = App.ChartLinearTimeView
 
   ajaxIndex: 'service.metrics.flume.sink_connection_failed',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.flume && hc.metrics.flume.flume && hc.metrics.flume.flume.SINK) {
-          for ( var cname in hc.metrics.flume.flume.SINK) {
-            var seriesName = Em.I18n.t('services.service.info.metrics.flume.sinkName').format(cname + " (" + hostName + ")");
-            var seriesData = hc.metrics.flume.flume.SINK[cname]['ConnectionFailedCount'];
-            if (seriesData) {
-              seriesArray.push(self.transformData(seriesData, seriesName));
-            }
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.flume.flume.SINK',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.sinkName').format(name + ' (' + hostName + ')');
+    },
+    flumePropertyName: 'ConnectionFailedCount'
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/sink_drain_success.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/sink_drain_success.js b/ambari-web/app/views/main/service/info/metrics/flume/sink_drain_success.js
index 4f2a7fb..2c6e9cf 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/sink_drain_success.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/sink_drain_success.js
@@ -32,27 +32,15 @@ App.ChartServiceMetricsFlume_SinkDrainSuccessCount = App.ChartLinearTimeView.ext
 
   ajaxIndex: 'service.metrics.flume.sink_drain_success',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.flume && hc.metrics.flume.flume && hc.metrics.flume.flume.SINK) {
-          for ( var cname in hc.metrics.flume.flume.SINK) {
-            var seriesName = Em.I18n.t('services.service.info.metrics.flume.sinkName').format(cname + " (" + hostName + ")");
-            var seriesData = hc.metrics.flume.flume.SINK[cname]['EventDrainSuccessCount'];
-            if (seriesData) {
-              seriesArray.push(self.transformData(seriesData, seriesName));
-            }
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.flume.flume.SINK',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.sinkName').format(name + ' (' + hostName + ')');
+    },
+    flumePropertyName: 'EventDrainSuccessCount'
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/flume/source_accepted.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/flume/source_accepted.js b/ambari-web/app/views/main/service/info/metrics/flume/source_accepted.js
index 434e487..9e28ef0 100644
--- a/ambari-web/app/views/main/service/info/metrics/flume/source_accepted.js
+++ b/ambari-web/app/views/main/service/info/metrics/flume/source_accepted.js
@@ -32,27 +32,15 @@ App.ChartServiceMetricsFlume_SourceAcceptedCount = App.ChartLinearTimeView.exten
 
   ajaxIndex: 'service.metrics.flume.source_accepted',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var self = this;
-    if (jsonData && jsonData.host_components) {
-      jsonData.host_components.forEach(function (hc) {
-        var hostName = hc.HostRoles.host_name;
-        var host = App.Host.find(hostName);
-        if (host && host.get('publicHostName')) {
-          hostName = host.get('publicHostName');
-        }
-        if (hc.metrics && hc.metrics.flume && hc.metrics.flume.flume && hc.metrics.flume.flume.SOURCE) {
-          for ( var cname in hc.metrics.flume.flume.SOURCE) {
-            var seriesName = Em.I18n.t('services.service.info.metrics.flume.sourceName').format(cname + " (" + hostName + ")");
-            var seriesData = hc.metrics.flume.flume.SOURCE[cname]['EventAcceptedCount'];
-            if (seriesData) {
-              seriesArray.push(self.transformData(seriesData, seriesName));
-            }
-          }
-        }
-      });
-    }
-    return seriesArray;
+  seriesTemplate: {
+    path: 'metrics.flume.flume.SOURCE',
+    displayName: function (name, hostName) {
+      return Em.I18n.t('services.service.info.metrics.flume.sourceName').format(name + ' (' + hostName + ')');
+    },
+    flumePropertyName: 'EventAcceptedCount'
+  },
+
+  getData: function (jsonData) {
+    return this.getFlumeData(jsonData);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/kafka/broker_topic.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/kafka/broker_topic.js b/ambari-web/app/views/main/service/info/metrics/kafka/broker_topic.js
index 16489e3..d584181 100644
--- a/ambari-web/app/views/main/service/info/metrics/kafka/broker_topic.js
+++ b/ambari-web/app/views/main/service/info/metrics/kafka/broker_topic.js
@@ -32,30 +32,19 @@ App.ChartServiceMetricsKafka_BrokerTopicMetrics = App.ChartLinearTimeView.extend
   renderer: 'line',
   ajaxIndex: 'service.metrics.kafka.broker.topic',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (Em.get(jsonData, 'metrics.kafka.server.BrokerTopicMetrics')) {
-      for (var name in Em.get(jsonData, 'metrics.kafka.server.BrokerTopicMetrics')) {
-        var displayName = null;
-        var seriesData = Em.get(jsonData, 'metrics.kafka.server.BrokerTopicMetrics.' + name + '.1MinuteRate');
-        switch (name) {
-          case "AllTopicsBytesOutPerSec":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsBytesOutPerSec');
-            break;
-          case "AllTopicsBytesInPerSec":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsBytesInPerSec');
-            break;
-          case "AllTopicsMessagesInPerSec":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsMessagesInPerSec');
-            break;
-          default:
-            break;
-        }
-        if (seriesData != null && displayName) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.kafka.server.BrokerTopicMetrics',
+    displayName: function (name) {
+      var displayNameMap = {
+        AllTopicsBytesOutPerSec: Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsBytesOutPerSec'),
+        AllTopicsBytesInPerSec: Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsBytesInPerSec'),
+        AllTopicsMessagesInPerSec: Em.I18n.t('services.service.info.metrics.kafka.server.brokerTopic.displayNames.AllTopicsMessagesInPerSec')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
+  },
+
+  getData: function (jsonData) {
+    return this.getKafkaData(jsonData);
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/kafka/controller_status.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/kafka/controller_status.js b/ambari-web/app/views/main/service/info/metrics/kafka/controller_status.js
index f8952ff..8610968 100644
--- a/ambari-web/app/views/main/service/info/metrics/kafka/controller_status.js
+++ b/ambari-web/app/views/main/service/info/metrics/kafka/controller_status.js
@@ -32,27 +32,18 @@ App.ChartServiceMetricsKafka_ControllerStatus = App.ChartLinearTimeView.extend({
   renderer: 'line',
   ajaxIndex: 'service.metrics.kafka.controller.ControllerStats',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (Em.get(jsonData, 'metrics.kafka.controller.ControllerStats')) {
-      for (var name in Em.get(jsonData, 'metrics.kafka.controller.ControllerStats')) {
-        var displayName = null;
-        var seriesData = Em.get(jsonData, 'metrics.kafka.controller.ControllerStats.' + name + '.1MinuteRate');
-        switch (name) {
-          case "LeaderElectionRateAndTimeMs":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.controller.ControllerStats.displayNames.LeaderElectionRateAndTimeMs');
-            break;
-          case "UncleanLeaderElectionsPerSec":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.controller.ControllerStats.displayNames.UncleanLeaderElectionsPerSec');
-            break;
-          default:
-            break;
-        }
-        if (seriesData != null && displayName) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.kafka.controller.ControllerStats',
+    displayName: function (name) {
+      var displayNameMap = {
+        LeaderElectionRateAndTimeMs: Em.I18n.t('services.service.info.metrics.kafka.controller.ControllerStats.displayNames.LeaderElectionRateAndTimeMs'),
+        UncleanLeaderElectionsPerSec: Em.I18n.t('services.service.info.metrics.kafka.controller.ControllerStats.displayNames.UncleanLeaderElectionsPerSec')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
+  },
+
+  getData: function (jsonData) {
+    return this.getKafkaData(jsonData);
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/kafka/kafka_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/kafka/kafka_controller.js b/ambari-web/app/views/main/service/info/metrics/kafka/kafka_controller.js
index 9432ab4..2f4fdd1 100644
--- a/ambari-web/app/views/main/service/info/metrics/kafka/kafka_controller.js
+++ b/ambari-web/app/views/main/service/info/metrics/kafka/kafka_controller.js
@@ -32,13 +32,10 @@ App.ChartServiceMetricsKafka_Controller = App.ChartLinearTimeView.extend({
   renderer: 'line',
   ajaxIndex: 'service.metrics.kafka.controller.KafkaController',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var seriesData = Em.get(jsonData, 'metrics.kafka.controller.KafkaController.ActiveControllerCount');
-    if (seriesData != null) {
-      var displayName = Em.I18n.t('services.service.info.metrics.kafka.controller.KafkaController.displayNames.ActiveControllerCount');
-      seriesArray.push(this.transformData(seriesData, displayName));
+  seriesTemplate: {
+    path: 'metrics.kafka.controller.KafkaController',
+    displayName: function () {
+      return Em.I18n.t('services.service.info.metrics.kafka.controller.KafkaController.displayNames.ActiveControllerCount');
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/kafka/replica_fetcher.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/kafka/replica_fetcher.js b/ambari-web/app/views/main/service/info/metrics/kafka/replica_fetcher.js
index a9375aa..7068c17 100644
--- a/ambari-web/app/views/main/service/info/metrics/kafka/replica_fetcher.js
+++ b/ambari-web/app/views/main/service/info/metrics/kafka/replica_fetcher.js
@@ -32,13 +32,10 @@ App.ChartServiceMetricsKafka_ReplicaFetcher = App.ChartLinearTimeView.extend({
   renderer: 'line',
   ajaxIndex: 'service.metrics.kafka.server.ReplicaFetcherManager',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    var seriesData = Em.get(jsonData, 'metrics.kafka.server.ReplicaFetcherManager.Replica-MaxLag');
-    if (seriesData != null) {
-      var displayName = Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaFetcherManager.displayNames.Replica-MaxLag');
-      seriesArray.push(this.transformData(seriesData, displayName));
+  seriesTemplate: {
+    path: 'metrics.kafka.server.ReplicaFetcherManager',
+    displayName: function () {
+      return Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaFetcherManager.displayNames.Replica-MaxLag');
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/app/views/main/service/info/metrics/kafka/replica_manager.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/metrics/kafka/replica_manager.js b/ambari-web/app/views/main/service/info/metrics/kafka/replica_manager.js
index 2eb745f..7452718 100644
--- a/ambari-web/app/views/main/service/info/metrics/kafka/replica_manager.js
+++ b/ambari-web/app/views/main/service/info/metrics/kafka/replica_manager.js
@@ -32,30 +32,15 @@ App.ChartServiceMetricsKafka_ReplicaManager = App.ChartLinearTimeView.extend({
   renderer: 'line',
   ajaxIndex: 'service.metrics.kafka.server.ReplicaManager',
 
-  transformToSeries: function (jsonData) {
-    var seriesArray = [];
-    if (Em.get(jsonData, 'metrics.kafka.server.ReplicaManager')) {
-      for (var name in Em.get(jsonData, 'metrics.kafka.server.ReplicaManager')) {
-        var displayName = null;
-        var seriesData = Em.get(jsonData, 'metrics.kafka.server.ReplicaManager.' + name);
-        switch (name) {
-          case "LeaderCount":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.LeaderCount');
-            break;
-          case "UnderReplicatedPartitions":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.UnderReplicatedPartitions');
-            break;
-          case "PartitionCount":
-            displayName = Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.PartitionCount');
-            break;
-          default:
-            break;
-        }
-        if (seriesData != null && displayName) {
-          seriesArray.push(this.transformData(seriesData, displayName));
-        }
-      }
+  seriesTemplate: {
+    path: 'metrics.kafka.server.ReplicaManager',
+    displayName: function (name) {
+      var displayNameMap = {
+        LeaderCount: Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.LeaderCount'),
+        UnderReplicatedPartitions: Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.UnderReplicatedPartitions'),
+        PartitionCount: Em.I18n.t('services.service.info.metrics.kafka.server.ReplicaManager.displayNames.PartitionCount')
+      };
+      return displayNameMap[name];
     }
-    return seriesArray;
   }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d6a54ace/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/chart/storm_linear_time_test.js b/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
index b9bc19b..9a573a4 100644
--- a/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
+++ b/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
@@ -60,17 +60,20 @@ describe('App.StormLinearTimeChartMixin', function () {
     });
   });
 
-  describe('#transformToSeries', function () {
+  describe('#getData', function () {
     it('should be empty', function () {
-      expect(slt.transformToSeries(jsonDataFalse)).to.be.empty;
+      expect(slt.getData(jsonDataFalse)).to.be.empty;
     });
     it('should take one element from data', function () {
       slt.set('transformData', function (data, name) {
         return name + ': ' + JSON.stringify(data);
       });
-      series = slt.transformToSeries(jsonDataTrue);
+      series = slt.getData(jsonDataTrue);
       expect(series).to.have.length(1);
-      expect(series[0]).to.equal('nimbus: "nimbus"');
+      expect(series[0]).to.eql({
+        name: 'nimbus',
+        data: 'nimbus'
+      });
     });
   });