Browse Source

AMBARI-1197. Refactor code for graphs. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1433668 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako 12 years ago
parent
commit
0cd4566d4e
34 changed files with 833 additions and 1153 deletions
  1. 2 0
      CHANGES.txt
  2. 542 520
      ambari-web/app/views/common/chart/linear_time.js
  3. 10 21
      ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js
  4. 8 20
      ambari-web/app/views/main/dashboard/cluster_metrics/load.js
  5. 8 19
      ambari-web/app/views/main/dashboard/cluster_metrics/memory.js
  6. 8 20
      ambari-web/app/views/main/dashboard/cluster_metrics/network.js
  7. 12 22
      ambari-web/app/views/main/host/metrics/cpu.js
  8. 13 20
      ambari-web/app/views/main/host/metrics/disk.js
  9. 9 20
      ambari-web/app/views/main/host/metrics/load.js
  10. 14 20
      ambari-web/app/views/main/host/metrics/memory.js
  11. 9 20
      ambari-web/app/views/main/host/metrics/network.js
  12. 9 20
      ambari-web/app/views/main/host/metrics/processes.js
  13. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/cluster_requests.js
  14. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/hlog_split_size.js
  15. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/hlog_split_time.js
  16. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/regionserver_queuesize.js
  17. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/regionserver_regions.js
  18. 7 19
      ambari-web/app/views/main/service/info/metrics/hbase/regionserver_rw_requests.js
  19. 9 20
      ambari-web/app/views/main/service/info/metrics/hdfs/block_status.js
  20. 9 20
      ambari-web/app/views/main/service/info/metrics/hdfs/file_operations.js
  21. 9 20
      ambari-web/app/views/main/service/info/metrics/hdfs/gc.js
  22. 7 19
      ambari-web/app/views/main/service/info/metrics/hdfs/io.js
  23. 13 21
      ambari-web/app/views/main/service/info/metrics/hdfs/jvm_heap.js
  24. 9 20
      ambari-web/app/views/main/service/info/metrics/hdfs/jvm_threads.js
  25. 9 20
      ambari-web/app/views/main/service/info/metrics/hdfs/rpc.js
  26. 13 20
      ambari-web/app/views/main/service/info/metrics/hdfs/space_utilization.js
  27. 9 20
      ambari-web/app/views/main/service/info/metrics/mapreduce/gc.js
  28. 7 19
      ambari-web/app/views/main/service/info/metrics/mapreduce/jobs_status.js
  29. 13 21
      ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_heap.js
  30. 10 20
      ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_threads.js
  31. 7 19
      ambari-web/app/views/main/service/info/metrics/mapreduce/map_slots.js
  32. 7 19
      ambari-web/app/views/main/service/info/metrics/mapreduce/reduce_slots.js
  33. 9 20
      ambari-web/app/views/main/service/info/metrics/mapreduce/rpc.js
  34. 7 19
      ambari-web/app/views/main/service/info/metrics/mapreduce/tasks_running_waiting.js

+ 2 - 0
CHANGES.txt

@@ -17,6 +17,8 @@ Trunk (unreleased changes):
 
  IMPROVEMENTS
 
+ AMBARI-1197. Refactor code for graphs. (yusaku)
+
  AMBARI-1196. Automatically update host-level popup info/logs. (yusaku)
 
  AMBARI-1189. Add App.Job class. (yusaku)

+ 542 - 520
ambari-web/app/views/common/chart/linear_time.js

@@ -46,553 +46,575 @@ var string_utils = require('utils/string_utils');
  * @extends Ember.View
  */
 App.ChartLinearTimeView = Ember.View.extend({
-      templateName: require('templates/main/charts/linear_time'),
-
-      /**
-       * The URL from which data can be retrieved.
-       * 
-       * This property must be provided for the graph to show properly.
-       * 
-       * @type String
-       * @default null
-       */
-      url: null,
-
-      /**
-       * A unique ID for this chart.
-       * 
-       * @type String
-       * @default null
-       */
-      id: null,
-
-      /**
-       * Title to be shown under the chart.
-       * 
-       * @type String
-       * @default null
-       */
-      title: null,
-
-      /**
-       * @private
-       * 
-       * @type Rickshaw.Graph
-       * @default null
-       */
-      _graph: null,
-
-      _popupGraph: null,
-
-      _seriesProperties: null,
-
-      renderer: 'area',
-
-      popupSuffix: '-popup',
-
-      isPopup: false,
-
-      isReady: false,
-
-      isPopupReady: false,
-
-      hasData: true,
-
-      /**
-       * Color palette used for this chart
-       *
-       * @private
-       * @type String[]
-       */
-       /*
-      _paletteScheme: [ 'rgba(181,182,169,0.4)', 'rgba(133,135,114,0.4)',
-          'rgba(120,95,67,0.4)', 'rgba(150,85,126,0.4)',
-          'rgba(70,130,180,0.4)', 'rgba(0,255,204,0.4)',
-          'rgba(255,105,180,0.4)', 'rgba(101,185,172,0.4)',
-          'rgba(115,192,58,0.4)', 'rgba(203,81,58,0.4)' ].reverse(),
-      */
-
-      selector: function () {
-        return '#' + this.get('elementId');
-      }.property('elementId'),
-
-      didInsertElement: function () {
-        this.loadData();
-        this.registerGraph();
-      },
-      registerGraph: function(){
-        var graph = {
-          name: this.get('title'),
-          id: this.get('elementId'),
-          popupId: this.get('id')
-        };
-        App.router.get('updateController.graphs').push(graph);
-      },
-
-      loadData: function() {
-        var validUrl = this.get('url');
-        if (validUrl) {
-          var hash = {};
-          hash.url = validUrl;
-          hash.type = 'GET';
-          hash.dataType = 'json';
-          hash.contentType = 'application/json; charset=utf-8';
-          hash.context = this;
-          hash.success = this._refreshGraph,
-           hash.error = function(xhr, textStatus, errorThrown){
-            this.set('isReady', true);
-            if (xhr.readyState == 4 && xhr.status) {
-              textStatus = xhr.status + " " + textStatus;
-            }
-            this._showMessage('warn', this.t('graphs.error.title'), this.t('graphs.error.message').format(textStatus, errorThrown));
-            this.set('isPopup', false);
-            this.set('hasData', false);
-          }
-          jQuery.ajax(hash);
-        }
-      },
-      
-      /**
-       * Shows a yellow warning message in place of the chart.
-       * 
-       * @param type  Can be any of 'warn', 'error', 'info', 'success'
-       * @param title Bolded title for the message
-       * @param message String representing the message
-       * @type: Function
-       */
-      _showMessage: function(type, title, message){
-        var chartOverlayId = '#' + this.id + '-chart';
-        if (this.get('isPopup')) {
-          chartOverlayId += this.get('popupSuffix');
-        }
-        var typeClass;
-        switch (type) {
-          case 'error':
-            typeClass = 'alert-error';
-            break;
-          case 'success':
-            typeClass = 'alert-success';
-            break;
-          case 'info':
-            typeClass = 'alert-info';
-            break;
-          default:
-            typeClass = '';
-            break;
-        }
-        $(chartOverlayId).html('');
-        $(chartOverlayId).append('<div class=\"alert '+typeClass+'\"><strong>'+title+'</strong> '+message+'</div>');
-      },
-
-      /**
-       * Transforms the JSON data retrieved from the server into the series
-       * format that Rickshaw.Graph understands.
-       * 
-       * The series object is generally in the following format: [ { name :
-       * "Series 1", data : [ { x : 0, y : 0 }, { x : 1, y : 1 } ] } ]
-       * 
-       * Extending classes should override this method.
-       * 
-       * @param jsonData
-       *          Data retrieved from the server
-       * @type: Function
-       * 
-       */
-      transformToSeries: function (jsonData) {
-        return [ {
-          name: "Series 1",
-          data: [ {
-            x: 0,
-            y: 0
-          }, {
-            x: 1,
-            y: 1
-          } ]
-        } ]
-      },
-
-      /**
-       * Provides the formatter to use in displaying Y axis.
-       * 
-       * The default is Rickshaw.Fixtures.Number.formatKMBT which shows 10K,
-       * 300M etc.
-       * 
-       * @type Function
-       */
-      yAxisFormatter: function(y) {
-        var value = Rickshaw.Fixtures.Number.formatKMBT(y);
-        if (value == '') return '0';
-        value = String(value);
-        var c = value[value.length - 1];
-        if (!isNaN(parseInt(c))) {
-          // c is digit
-          value = parseFloat(value).toFixed(3).replace(/0+$/, '').replace(/\.$/, '');
-        }
-        else {
-          // c in not digit
-          value = parseFloat(value.substr(0, value.length - 1)).toFixed(3).replace(/0+$/, '').replace(/\.$/, '') + c;
-        }
-        return value;
-      },
-
-      /**
-       * Provides the color (in any HTML color format) to use for a particular
-       * series.
-       *
-       * @param series
-       *          Series for which color is being requested
-       * @return color String. Returning null allows this chart to pick a color
-       *         from palette.
-       * @default null
-       * @type Function
-       */
-      colorForSeries: function (series) {
-        return null;
-      },
+  templateName: require('templates/main/charts/linear_time'),
 
   /**
-   * Check whether seriesData is correct data for chart drawing
-   * @param seriesData
-   * @return {Boolean}
+   * The URL from which data can be retrieved.
+   *
+   * This property must be provided for the graph to show properly.
+   *
+   * @type String
+   * @default null
    */
-      checkSeries : function(seriesData){
-        if(!seriesData || !seriesData.length){
-          return false;
-        }
-        var result = true;
-        seriesData.forEach(function(item){
-          if(!item.data.length || !item.data[0] || typeof item.data[0].x === 'undefined'){
-            result = false;
-          }
-        });
-        return result;
-      },
-
-      /**
-       * @private
-       * 
-       * Refreshes the graph with the latest JSON data.
-       * 
-       * @type Function
-       */
-      _refreshGraph: function (jsonData) {
-        var seriesData = this.transformToSeries(jsonData);
-
-        if (this.checkSeries(seriesData)) {
-          //if graph opened as modal popup
-          var popup_path = $("#" + this.id + "-container" + this.get('popupSuffix'));
-          var graph_container = $("#" + this.id + "-container");
-          if(popup_path.length) {
-            popup_path.children().each(function () {
-              $(this).children().remove();
-            });
-            this.set('isPopup', true);
-          }
-          else {
-            graph_container.children().each(function (index, value) {
-              $(value).children().remove();
-            });
-          }
-          // Check container exists (may be not, if we go to another page and wait while graphs loading)
-          if (graph_container.length) {
-            this.draw(seriesData);
-            this.set('hasData', true);
-          }
-        }
-        else {
-          this.set('isReady', true);
-          this._showMessage('info', this.t('graphs.noData.title'), this.t('graphs.noData.message'));
-          this.set('isPopup', false);
-          this.set('hasData', false);
-        }
-      },
-      
-      /**
-       * Returns a custom time unit for the graph's X axis. This is needed
-       * as Rickshaw's default time X axis uses UTC time, which can be confusing
-       * for users expecting locale specific time. This value defaults to
-       * App.ChartLinearTimeView.FifteenMinuteTimeUnit.
-       * 
-       * If <code>null</code> is returned, Rickshaw's default time unit is used.
-       * 
-       * @type Function
-       * @return Rickshaw.Fixtures.Time
-       * @default App.ChartLinearTimeView.FifteenMinuteTimeUnit
-       */
-      localeTimeUnit: function(){
-        return App.ChartLinearTimeView.FifteenMinuteTimeUnit;
-      },
-
-      /**
-       * @private
-       * 
-       * When a graph is given a particular width and height,the lines are drawn
-       * in a slightly bigger area thereby chopping off some of the UI. Hence
-       * after the rendering, we adjust the SVGs size in the DOM to compensate.
-       * 
-       * Opened https://github.com/shutterstock/rickshaw/issues/141
-       * 
-       * @type Function
-       */
-      _adjustSVGHeight: function () {
-        if (this._graph && this._graph.element
-            && this._graph.element.firstChild) {
-          var svgElement = this._graph.element.firstChild;
-          svgElement.setAttribute('height', $(this._graph.element).height()
-              + "px");
-          svgElement.setAttribute('width', $(this._graph.element).width()
-              + "px");
-        }
-      },
+  url: null,
 
-      draw: function(seriesData) {
-        var isPopup = this.get('isPopup');
-        var p = '';
-        if (isPopup) {
-          p = this.get('popupSuffix');
-        }
-        var palette = new Rickshaw.Color.Palette({ scheme: 'munin'});
-
-        // var palette = new Rickshaw.Color.Palette({
-        //   scheme: this._paletteScheme
-        // });
-
-        var self = this;
-        var series_min_length = 100000000;
-        seriesData.forEach(function (series, index) {
-          var seriesColor = self.colorForSeries(series);
-          if (seriesColor == null) {
-            seriesColor = palette.color();
-          }
-          series.color = seriesColor;
-          series.stroke = 'rgba(0,0,0,0.3)';
-          if (isPopup) {
-            // calculate statistic data for popup legend
-            var avg = 0;
-            var min = Number.MAX_VALUE;
-            var max = Number.MIN_VALUE;
-            for (var i = 0; i < series.data.length; i++) {
-              avg += series.data[i]['y'];
-              if (series.data[i]['y'] < min) {
-                min = series.data[i]['y'];
-              }
-              else {
-                if (series.data[i]['y'] > max) {
-                  max = series.data[i]['y'];
-                }
-              }
-            }
-            series.name = string_utils.pad(series.name, 30, '&nbsp;', 2) + string_utils.pad('min', 5, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(min), 12, '&nbsp;', 3) + string_utils.pad('avg', 5, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(avg/series.data.length), 12, '&nbsp;', 3) + string_utils.pad('max', 12, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(max), 5, '&nbsp;', 3);
-          }
-          if (series.data.length < series_min_length) {
-            series_min_length = series.data.length;
-          }
-        }.bind(this));
-        seriesData.forEach(function(series, index) {
-          if (series.data.length > series_min_length) {
-            series.data.length = series_min_length;
-          }
-        });
-        var chartId = "#" + this.id + "-chart" + p;
-        var chartOverlayId = "#" + this.id + "-container" + p;
-        var xaxisElementId = "#" + this.id + "-xaxis" + p;
-        var yaxisElementId = "#" + this.id + "-yaxis" + p;
-        var legendElementId = "#" + this.id + "-legend" + p;
-
-        var chartElement = document.querySelector(chartId);
-        var overlayElement = document.querySelector(chartOverlayId);
-        var xaxisElement = document.querySelector(xaxisElementId);
-        var yaxisElement = document.querySelector(yaxisElementId);
-        var legendElement = document.querySelector(legendElementId);
-
-        var strokeWidth = 1;
-        if (this.get('renderer') != 'area') {
-          strokeWidth = 2;
-        }
+  /**
+   * A unique ID for this chart.
+   *
+   * @type String
+   * @default null
+   */
+  id: null,
 
-        var height = 150;
-        var width = 400;
-        if (isPopup) {
-          height = 180;
-          width = 670;
-        } else {
-          // If not in popup, the width could vary.
-          // We determine width based on div's size.
-          var thisElement = this.get('element');
-          if (thisElement!=null) {
-            var calculatedWidth = $(thisElement).width();
-            if (calculatedWidth > 32) {
-              width = calculatedWidth-32;
-            }
-          }
-        }
-        var _graph = new Rickshaw.Graph({
-          height: height,
-          width: width,
-          element: chartElement,
-          series: seriesData,
-          interpolation: 'step-after',
-          stroke: true,
-          renderer: this.get('renderer'),
-          strokeWidth: strokeWidth
-        });
-        if (this.get('renderer') === 'area') {
-          _graph.renderer.unstack = false;
-        }
+  /**
+   * Title to be shown under the chart.
+   *
+   * @type String
+   * @default null
+   */
+  title: null,
 
-        xAxis = new Rickshaw.Graph.Axis.Time({
-          graph: _graph,
-          timeUnit: this.localeTimeUnit()
-        });
+  /**
+   * @private
+   *
+   * @type Rickshaw.Graph
+   * @default null
+   */
+  _graph: null,
 
-        var orientation = 'right';
-        if (isPopup) {
-          orientation = 'left';
-        }
-        yAxis = new Rickshaw.Graph.Axis.Y({
-          tickFormat: this.yAxisFormatter,
-          element: yaxisElement,
-          orientation: orientation,
-          graph: _graph
-        });
+  _popupGraph: null,
 
-        var legend = new Rickshaw.Graph.Legend({
-          graph: _graph,
-          element: legendElement
-        });
+  _seriesProperties: null,
+
+  renderer: 'area',
+
+  popupSuffix: '-popup',
+
+  isPopup: false,
 
-        if (!isPopup) {
-          overlayElement.addEventListener('mousemove', function () {
-            $(xaxisElement).removeClass('hide');
-            $(legendElement).removeClass('hide');
-            $(chartElement).children("div").removeClass('hide');
-          });
-          overlayElement.addEventListener('mouseout', function () {
-            $(legendElement).addClass('hide');
-          });
-          _graph.onUpdate(function () {
-            $(legendElement).addClass('hide');
-          });
+  isReady: false,
+
+  isPopupReady: false,
+
+  hasData: true,
+  /**
+   * Current cluster name
+   */
+  clusterName: function() {
+    return App.router.get('clusterController.clusterName');
+  }.property('App.router.clusterController.clusterName'),
+  /**
+   * Url prefix common for all child views
+   */
+  urlPrefix: function() {
+    return App.apiPrefix + "/clusters/" + this.get('clusterName');
+  }.property('clusterName'),
+
+  /**
+   * Color palette used for this chart
+   *
+   * @private
+   * @type String[]
+   */
+   /*
+  _paletteScheme: [ 'rgba(181,182,169,0.4)', 'rgba(133,135,114,0.4)',
+      'rgba(120,95,67,0.4)', 'rgba(150,85,126,0.4)',
+      'rgba(70,130,180,0.4)', 'rgba(0,255,204,0.4)',
+      'rgba(255,105,180,0.4)', 'rgba(101,185,172,0.4)',
+      'rgba(115,192,58,0.4)', 'rgba(203,81,58,0.4)' ].reverse(),
+  */
+
+  selector: function () {
+    return '#' + this.get('elementId');
+  }.property('elementId'),
+
+  didInsertElement: function () {
+    this.loadData();
+    this.registerGraph();
+  },
+  registerGraph: function(){
+    var graph = {
+      name: this.get('title'),
+      id: this.get('elementId'),
+      popupId: this.get('id')
+    };
+    App.router.get('updateController.graphs').push(graph);
+  },
+
+  loadData: function() {
+    var validUrl = this.get('url');
+    if (validUrl) {
+      var hash = {};
+      hash.url = validUrl;
+      hash.type = 'GET';
+      hash.dataType = 'json';
+      hash.contentType = 'application/json; charset=utf-8';
+      hash.context = this;
+      hash.success = this._refreshGraph,
+       hash.error = function(xhr, textStatus, errorThrown){
+        this.set('isReady', true);
+        if (xhr.readyState == 4 && xhr.status) {
+          textStatus = xhr.status + " " + textStatus;
         }
+        this._showMessage('warn', this.t('graphs.error.title'), this.t('graphs.error.message').format(textStatus, errorThrown));
+        this.set('isPopup', false);
+        this.set('hasData', false);
+      }
+      jQuery.ajax(hash);
+    }
+  },
 
-       var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
-          graph: _graph,
-          legend: legend
+  /**
+   * Shows a yellow warning message in place of the chart.
+   *
+   * @param type  Can be any of 'warn', 'error', 'info', 'success'
+   * @param title Bolded title for the message
+   * @param message String representing the message
+   * @type: Function
+   */
+  _showMessage: function(type, title, message){
+    var chartOverlayId = '#' + this.id + '-chart';
+    if (this.get('isPopup')) {
+      chartOverlayId += this.get('popupSuffix');
+    }
+    var typeClass;
+    switch (type) {
+      case 'error':
+        typeClass = 'alert-error';
+        break;
+      case 'success':
+        typeClass = 'alert-success';
+        break;
+      case 'info':
+        typeClass = 'alert-info';
+        break;
+      default:
+        typeClass = '';
+        break;
+    }
+    $(chartOverlayId).html('');
+    $(chartOverlayId).append('<div class=\"alert '+typeClass+'\"><strong>'+title+'</strong> '+message+'</div>');
+  },
+
+  /**
+   * Transforms the JSON data retrieved from the server into the series
+   * format that Rickshaw.Graph understands.
+   *
+   * The series object is generally in the following format: [ { name :
+   * "Series 1", data : [ { x : 0, y : 0 }, { x : 1, y : 1 } ] } ]
+   *
+   * Extending classes should override this method.
+   *
+   * @param seriesData
+   *          Data retrieved from the server
+   * @param displayName
+   *          Graph title
+   * @type: Function
+   *
+   */
+  transformData: function (seriesData, displayName) {
+    var seriesArray = [];
+    if (seriesData) {
+      // Is it a string?
+      if ("string" == typeof seriesData) {
+        seriesData = JSON.parse(seriesData);
+      }
+      // We have valid data
+      var series = {};
+      series.name = displayName;
+      series.data = [];
+      for ( var index = 0; index < seriesData.length; index++) {
+        series.data.push({
+          x: seriesData[index][1],
+          y: seriesData[index][0]
         });
+      }
+      return series;
+    }
+  },
 
-        var order = new Rickshaw.Graph.Behavior.Series.Order({
-          graph: _graph,
-          legend: legend
+  /**
+   * Provides the formatter to use in displaying Y axis.
+   *
+   * The default is Rickshaw.Fixtures.Number.formatKMBT which shows 10K,
+   * 300M etc.
+   *
+   * @type Function
+   */
+  yAxisFormatter: function(y) {
+    var value = Rickshaw.Fixtures.Number.formatKMBT(y);
+    if (value == '') return '0';
+    value = String(value);
+    var c = value[value.length - 1];
+    if (!isNaN(parseInt(c))) {
+      // c is digit
+      value = parseFloat(value).toFixed(3).replace(/0+$/, '').replace(/\.$/, '');
+    }
+    else {
+      // c in not digit
+      value = parseFloat(value.substr(0, value.length - 1)).toFixed(3).replace(/0+$/, '').replace(/\.$/, '') + c;
+    }
+    return value;
+  },
+
+  /**
+   * Provides the color (in any HTML color format) to use for a particular
+   * series.
+   *
+   * @param series
+   *          Series for which color is being requested
+   * @return color String. Returning null allows this chart to pick a color
+   *         from palette.
+   * @default null
+   * @type Function
+   */
+  colorForSeries: function (series) {
+    return null;
+  },
+
+  /**
+  * Check whether seriesData is correct data for chart drawing
+  * @param seriesData
+  * @return {Boolean}
+  */
+  checkSeries : function(seriesData){
+    if(!seriesData || !seriesData.length){
+      return false;
+    }
+    var result = true;
+    seriesData.forEach(function(item){
+      if(!item.data.length || !item.data[0] || typeof item.data[0].x === 'undefined'){
+        result = false;
+      }
+    });
+    return result;
+  },
+
+  /**
+   * @private
+   *
+   * Refreshes the graph with the latest JSON data.
+   *
+   * @type Function
+   */
+  _refreshGraph: function (jsonData) {
+    var seriesData = this.transformToSeries(jsonData);
+
+    if (this.checkSeries(seriesData)) {
+      //if graph opened as modal popup
+      var popup_path = $("#" + this.id + "-container" + this.get('popupSuffix'));
+      var graph_container = $("#" + this.id + "-container");
+      if(popup_path.length) {
+        popup_path.children().each(function () {
+          $(this).children().remove();
         });
-        //show the graph when it's loaded
-        _graph.onUpdate(function(){
-          self.set('isReady', true);
+        this.set('isPopup', true);
+      }
+      else {
+        graph_container.children().each(function (index, value) {
+          $(value).children().remove();
         });
-        _graph.render();
-
-        if (isPopup) {
-          var self = this;
-          var hoverDetail = new Rickshaw.Graph.HoverDetail({
-            graph: _graph,
-            yFormatter:function (y) {
-              return self.yAxisFormatter(y);
-            },
-            xFormatter:function (x) {
-              return (new Date(x * 1000)).toLocaleTimeString();
-            },
-            formatter:function (series, x, y, formattedX, formattedY, d) {
-              return formattedY + '<br />' + formattedX;
-            }
-          });
-        }
+      }
+      // Check container exists (may be not, if we go to another page and wait while graphs loading)
+      if (graph_container.length) {
+        this.draw(seriesData);
+        this.set('hasData', true);
+      }
+    }
+    else {
+      this.set('isReady', true);
+      this._showMessage('info', this.t('graphs.noData.title'), this.t('graphs.noData.message'));
+      this.set('isPopup', false);
+      this.set('hasData', false);
+    }
+  },
+
+  /**
+   * Returns a custom time unit for the graph's X axis. This is needed
+   * as Rickshaw's default time X axis uses UTC time, which can be confusing
+   * for users expecting locale specific time. This value defaults to
+   * App.ChartLinearTimeView.FifteenMinuteTimeUnit.
+   *
+   * If <code>null</code> is returned, Rickshaw's default time unit is used.
+   *
+   * @type Function
+   * @return Rickshaw.Fixtures.Time
+   * @default App.ChartLinearTimeView.FifteenMinuteTimeUnit
+   */
+  localeTimeUnit: function(){
+    return App.ChartLinearTimeView.FifteenMinuteTimeUnit;
+  },
+
+  /**
+   * @private
+   *
+   * When a graph is given a particular width and height,the lines are drawn
+   * in a slightly bigger area thereby chopping off some of the UI. Hence
+   * after the rendering, we adjust the SVGs size in the DOM to compensate.
+   *
+   * Opened https://github.com/shutterstock/rickshaw/issues/141
+   *
+   * @type Function
+   */
+  _adjustSVGHeight: function () {
+    if (this._graph && this._graph.element
+        && this._graph.element.firstChild) {
+      var svgElement = this._graph.element.firstChild;
+      svgElement.setAttribute('height', $(this._graph.element).height()
+          + "px");
+      svgElement.setAttribute('width', $(this._graph.element).width()
+          + "px");
+    }
+  },
 
-        if (isPopup) {
-          var self = this;
-          // In popup save selected metrics and show only them after data update
-          _graph.series.forEach(function(series, index) {
-            if (self.get('_seriesProperties') !== null && self.get('_seriesProperties')[index] !== null) {
-              if(self.get('_seriesProperties')[self.get('_seriesProperties').length - index - 1].length > 1) {
-                $('#'+self.get('id')+'-container'+self.get('popupSuffix')+' a.action:eq('+(self.get('_seriesProperties').length - index - 1)+')').parent('li').addClass('disabled');
-                series.disable();
-              }
+  draw: function(seriesData) {
+    var isPopup = this.get('isPopup');
+    var p = '';
+    if (isPopup) {
+      p = this.get('popupSuffix');
+    }
+    var palette = new Rickshaw.Color.Palette({ scheme: 'munin'});
+
+    // var palette = new Rickshaw.Color.Palette({
+    //   scheme: this._paletteScheme
+    // });
+
+    var self = this;
+    var series_min_length = 100000000;
+    seriesData.forEach(function (series, index) {
+      var seriesColor = self.colorForSeries(series);
+      if (seriesColor == null) {
+        seriesColor = palette.color();
+      }
+      series.color = seriesColor;
+      series.stroke = 'rgba(0,0,0,0.3)';
+      if (isPopup) {
+        // calculate statistic data for popup legend
+        var avg = 0;
+        var min = Number.MAX_VALUE;
+        var max = Number.MIN_VALUE;
+        for (var i = 0; i < series.data.length; i++) {
+          avg += series.data[i]['y'];
+          if (series.data[i]['y'] < min) {
+            min = series.data[i]['y'];
+          }
+          else {
+            if (series.data[i]['y'] > max) {
+              max = series.data[i]['y'];
             }
-          });
-          //show the graph when it's loaded
-          _graph.onUpdate(function(){
-            self.set('isPopupReady', true);
-          });
-          _graph.update();
-
-          $('li.line').click(function() {
-            var series = [];
-            $('#'+self.get('id')+'-container'+self.get('popupSuffix')+' a.action').each(function(index, v) {
-              series[index] = v.parentNode.classList;
-            });
-            self.set('_seriesProperties', series);
-          });
-
-          this.set('_popupGraph', _graph);
+          }
         }
-        else {
-          this.set('_graph', _graph);
+        series.name = string_utils.pad(series.name, 30, '&nbsp;', 2) + string_utils.pad('min', 5, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(min), 12, '&nbsp;', 3) + string_utils.pad('avg', 5, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(avg/series.data.length), 12, '&nbsp;', 3) + string_utils.pad('max', 12, '&nbsp;', 3) + string_utils.pad(this.get('yAxisFormatter')(max), 5, '&nbsp;', 3);
+      }
+      if (series.data.length < series_min_length) {
+        series_min_length = series.data.length;
+      }
+    }.bind(this));
+    seriesData.forEach(function(series, index) {
+      if (series.data.length > series_min_length) {
+        series.data.length = series_min_length;
+      }
+    });
+    var chartId = "#" + this.id + "-chart" + p;
+    var chartOverlayId = "#" + this.id + "-container" + p;
+    var xaxisElementId = "#" + this.id + "-xaxis" + p;
+    var yaxisElementId = "#" + this.id + "-yaxis" + p;
+    var legendElementId = "#" + this.id + "-legend" + p;
+
+    var chartElement = document.querySelector(chartId);
+    var overlayElement = document.querySelector(chartOverlayId);
+    var xaxisElement = document.querySelector(xaxisElementId);
+    var yaxisElement = document.querySelector(yaxisElementId);
+    var legendElement = document.querySelector(legendElementId);
+
+    var strokeWidth = 1;
+    if (this.get('renderer') != 'area') {
+      strokeWidth = 2;
+    }
+
+    var height = 150;
+    var width = 400;
+    if (isPopup) {
+      height = 180;
+      width = 670;
+    } else {
+      // If not in popup, the width could vary.
+      // We determine width based on div's size.
+      var thisElement = this.get('element');
+      if (thisElement!=null) {
+        var calculatedWidth = $(thisElement).width();
+        if (calculatedWidth > 32) {
+          width = calculatedWidth-32;
         }
-        this.set('isPopup', false);
-      },
+      }
+    }
+    var _graph = new Rickshaw.Graph({
+      height: height,
+      width: width,
+      element: chartElement,
+      series: seriesData,
+      interpolation: 'step-after',
+      stroke: true,
+      renderer: this.get('renderer'),
+      strokeWidth: strokeWidth
+    });
+    if (this.get('renderer') === 'area') {
+      _graph.renderer.unstack = false;
+    }
+
+    xAxis = new Rickshaw.Graph.Axis.Time({
+      graph: _graph,
+      timeUnit: this.localeTimeUnit()
+    });
+
+    var orientation = 'right';
+    if (isPopup) {
+      orientation = 'left';
+    }
+    yAxis = new Rickshaw.Graph.Axis.Y({
+      tickFormat: this.yAxisFormatter,
+      element: yaxisElement,
+      orientation: orientation,
+      graph: _graph
+    });
+
+    var legend = new Rickshaw.Graph.Legend({
+      graph: _graph,
+      element: legendElement
+    });
+
+    if (!isPopup) {
+      overlayElement.addEventListener('mousemove', function () {
+        $(xaxisElement).removeClass('hide');
+        $(legendElement).removeClass('hide');
+        $(chartElement).children("div").removeClass('hide');
+      });
+      overlayElement.addEventListener('mouseout', function () {
+        $(legendElement).addClass('hide');
+      });
+      _graph.onUpdate(function () {
+        $(legendElement).addClass('hide');
+      });
+    }
 
+   var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
+      graph: _graph,
+      legend: legend
+    });
 
-      showGraphInPopup: function() {
-        if(!this.get('hasData')){
-          return;
+    var order = new Rickshaw.Graph.Behavior.Series.Order({
+      graph: _graph,
+      legend: legend
+    });
+    //show the graph when it's loaded
+    _graph.onUpdate(function(){
+      self.set('isReady', true);
+    });
+    _graph.render();
+
+    if (isPopup) {
+      var self = this;
+      var hoverDetail = new Rickshaw.Graph.HoverDetail({
+        graph: _graph,
+        yFormatter:function (y) {
+          return self.yAxisFormatter(y);
+        },
+        xFormatter:function (x) {
+          return (new Date(x * 1000)).toLocaleTimeString();
+        },
+        formatter:function (series, x, y, formattedX, formattedY, d) {
+          return formattedY + '<br />' + formattedX;
         }
+      });
+    }
 
-        this.set('isPopup', true);
-        var self = this;
-        App.ModalPopup.show({
-          template: Ember.Handlebars.compile([
-            '<div class="modal-backdrop"></div><div class="modal modal-graph-line" id="modal" tabindex="-1" role="dialog" aria-labelledby="modal-label" aria-hidden="true">',
-            '<div class="modal-header">',
-            '<a class="close" {{action onClose target="view"}}>x</a>',
-            '<h3 id="modal-label">',
-            '{{#if headerClass}}{{view headerClass}}',
-            '{{else}}{{header}}{{/if}}',
-            '</h3>',
-            '</div>',
-            '<div class="modal-body">',
-            '{{#if bodyClass}}{{view bodyClass}}',
-            '{{else}}',
-              '<div class="screensaver no-borders chart-container" {{bindAttr class="view.isReady:hide"}} ></div>',
-              '<div id="'+this.get('id')+'-container'+this.get('popupSuffix')+'" class="chart-container chart-container'+this.get('popupSuffix')+' hide" {{bindAttr class="view.isReady:show"}} >',
-                '<div id="'+this.get('id')+'-yaxis'+this.get('popupSuffix')+'" class="'+this.get('id')+'-yaxis chart-y-axis"></div>',
-                '<div id="'+this.get('id')+'-xaxis'+this.get('popupSuffix')+'" class="'+this.get('id')+'-xaxis chart-x-axis"></div>',
-                '<div id="'+this.get('id')+'-legend'+this.get('popupSuffix')+'" class="'+this.get('id')+'-legend chart-legend"></div>',
-                '<div id="'+this.get('id')+'-chart'+this.get('popupSuffix')+'" class="'+this.get('id')+'-chart chart"></div>',
-                '<div id="'+this.get('id')+'-title'+this.get('popupSuffix')+'" class="'+this.get('id')+'-title chart-title">{{view.title}}</div>'+
-              '</div>',
-            '{{/if}}',
-            '</div>',
-            '<div class="modal-footer">',
-            '{{#if view.primary}}<a class="btn btn-success" {{action onPrimary target="view"}}>{{view.primary}}</a>{{/if}}',
-            '</div>',
-            '</div>'
-          ].join('\n')),
-
-          header: this.get('title'),
-          self: self,
-          isReady: function(){
-            return this.get('self.isPopupReady');
-          }.property('self.isPopupReady'),
-          primary: 'OK',
-          onPrimary: function() {
-            this.hide();
-            self.set('isPopup', false);
+    if (isPopup) {
+      var self = this;
+      // In popup save selected metrics and show only them after data update
+      _graph.series.forEach(function(series, index) {
+        if (self.get('_seriesProperties') !== null && self.get('_seriesProperties')[index] !== null) {
+          if(self.get('_seriesProperties')[self.get('_seriesProperties').length - index - 1].length > 1) {
+            $('#'+self.get('id')+'-container'+self.get('popupSuffix')+' a.action:eq('+(self.get('_seriesProperties').length - index - 1)+')').parent('li').addClass('disabled');
+            series.disable();
           }
+        }
+      });
+      //show the graph when it's loaded
+      _graph.onUpdate(function(){
+        self.set('isPopupReady', true);
+      });
+      _graph.update();
+
+      $('li.line').click(function() {
+        var series = [];
+        $('#'+self.get('id')+'-container'+self.get('popupSuffix')+' a.action').each(function(index, v) {
+          series[index] = v.parentNode.classList;
         });
-        Ember.run.next(function() {
-          self.loadData();
-          self.set('isPopupReady', false);
-        });
+        self.set('_seriesProperties', series);
+      });
+
+      this.set('_popupGraph', _graph);
+    }
+    else {
+      this.set('_graph', _graph);
+    }
+    this.set('isPopup', false);
+  },
+
+
+  showGraphInPopup: function() {
+    if(!this.get('hasData')){
+      return;
+    }
+
+    this.set('isPopup', true);
+    var self = this;
+    App.ModalPopup.show({
+      template: Ember.Handlebars.compile([
+        '<div class="modal-backdrop"></div><div class="modal modal-graph-line" id="modal" tabindex="-1" role="dialog" aria-labelledby="modal-label" aria-hidden="true">',
+        '<div class="modal-header">',
+        '<a class="close" {{action onClose target="view"}}>x</a>',
+        '<h3 id="modal-label">',
+        '{{#if headerClass}}{{view headerClass}}',
+        '{{else}}{{header}}{{/if}}',
+        '</h3>',
+        '</div>',
+        '<div class="modal-body">',
+        '{{#if bodyClass}}{{view bodyClass}}',
+        '{{else}}',
+          '<div class="screensaver no-borders chart-container" {{bindAttr class="view.isReady:hide"}} ></div>',
+          '<div id="'+this.get('id')+'-container'+this.get('popupSuffix')+'" class="chart-container chart-container'+this.get('popupSuffix')+' hide" {{bindAttr class="view.isReady:show"}} >',
+            '<div id="'+this.get('id')+'-yaxis'+this.get('popupSuffix')+'" class="'+this.get('id')+'-yaxis chart-y-axis"></div>',
+            '<div id="'+this.get('id')+'-xaxis'+this.get('popupSuffix')+'" class="'+this.get('id')+'-xaxis chart-x-axis"></div>',
+            '<div id="'+this.get('id')+'-legend'+this.get('popupSuffix')+'" class="'+this.get('id')+'-legend chart-legend"></div>',
+            '<div id="'+this.get('id')+'-chart'+this.get('popupSuffix')+'" class="'+this.get('id')+'-chart chart"></div>',
+            '<div id="'+this.get('id')+'-title'+this.get('popupSuffix')+'" class="'+this.get('id')+'-title chart-title">{{view.title}}</div>'+
+          '</div>',
+        '{{/if}}',
+        '</div>',
+        '<div class="modal-footer">',
+        '{{#if view.primary}}<a class="btn btn-success" {{action onPrimary target="view"}}>{{view.primary}}</a>{{/if}}',
+        '</div>',
+        '</div>'
+      ].join('\n')),
+
+      header: this.get('title'),
+      self: self,
+      isReady: function(){
+        return this.get('self.isPopupReady');
+      }.property('self.isPopupReady'),
+      primary: 'OK',
+      onPrimary: function() {
+        this.hide();
+        self.set('isPopup', false);
       }
     });
+    Ember.run.next(function() {
+      self.loadData();
+      self.set('isPopupReady', false);
+    });
+  }
+});
 
 /**
  * A formatter which will turn a number into computer storage sizes of the

+ 10 - 21
ambari-web/app/views/main/dashboard/cluster_metrics/cpu.js

@@ -29,10 +29,12 @@ var App = require('app');
 App.ChartClusterMetricsCPU = App.ChartLinearTimeView.extend({
   id: "cluster-metrics-cpu",
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}?fields=metrics/cpu[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/cluster_metrics/cpu_1hr.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "?fields=metrics/cpu[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/cluster_metrics/cpu_1hr.json"
+    );
+  }.property('clusterName').volatile(),
 
   title: "CPU Usage",
   yAxisFormatter: App.ChartLinearTimeView.PercentageFormatter,
@@ -45,25 +47,12 @@ App.ChartClusterMetricsCPU = App.ChartLinearTimeView.extend({
         var displayName = name;
         var seriesData = jsonData.metrics.cpu[name];
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          if (name != 'Idle') {
-            seriesArray.push(series);
+          var s = this.transformData(seriesData, displayName);
+          if ('Idle' == s.name) {
+            cpu_idle = s;
           }
           else {
-            cpu_idle = series;
+            seriesArray.push(s);
           }
         }
       }

+ 8 - 20
ambari-web/app/views/main/dashboard/cluster_metrics/load.js

@@ -29,12 +29,14 @@ var App = require('app');
  */
 App.ChartClusterMetricsLoad = App.ChartLinearTimeView.extend({
   id: "cluster-metrics-load",
-  url: "/data/cluster_metrics/load_1hr.json",
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}?fields=metrics/load[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/cluster_metrics/load_1hr.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "?fields=metrics/load[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/cluster_metrics/load_1hr.json"
+    );
+  }.property('clusterName').volatile(),
+
   renderer: 'line',
   title: "Cluster Load",
   
@@ -45,21 +47,7 @@ App.ChartClusterMetricsLoad = App.ChartLinearTimeView.extend({
         var displayName = name;
         var seriesData = jsonData.metrics.load[name];
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 8 - 19
ambari-web/app/views/main/dashboard/cluster_metrics/memory.js

@@ -29,10 +29,13 @@ var App = require('app');
 App.ChartClusterMetricsMemory = App.ChartLinearTimeView.extend({
   id: "cluster-metrics-memory",
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}?fields=metrics/memory[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/cluster_metrics/memory_1hr.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "?fields=metrics/memory[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/cluster_metrics/memory_1hr.json"
+    );
+  }.property('clusterName').volatile(),
+
   title: "Memory Usage",
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
@@ -43,21 +46,7 @@ App.ChartClusterMetricsMemory = App.ChartLinearTimeView.extend({
         var displayName = name;
         var seriesData = jsonData.metrics.memory[name];
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 8 - 20
ambari-web/app/views/main/dashboard/cluster_metrics/network.js

@@ -30,10 +30,13 @@ var App = require('app');
 App.ChartClusterMetricsNetwork = App.ChartLinearTimeView.extend({
   id: "cluster-metrics-network",
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}?fields=metrics/network[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/cluster_metrics/network_1hr.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "?fields=metrics/network[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/cluster_metrics/network_1hr.json"
+    );
+  }.property('clusterName').volatile(),
+
   title: "Network Usage",
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
@@ -45,22 +48,7 @@ App.ChartClusterMetricsNetwork = App.ChartLinearTimeView.extend({
         var displayName = name;
         var seriesData = jsonData.metrics.network[name];
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 12 - 22
ambari-web/app/views/main/host/metrics/cpu.js

@@ -33,11 +33,14 @@ App.ChartHostMetricsCPU = App.ChartLinearTimeView.extend({
 
 
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/cpu/cpu_user[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_wio[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_nice[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_aidle[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_system[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_idle[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/cpu.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/cpu/cpu_user[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_wio[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_nice[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_aidle[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_system[{fromSeconds},{toSeconds},{stepSeconds}],metrics/cpu/cpu_idle[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/cpu.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -69,25 +72,12 @@ App.ChartHostMetricsCPU = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          if (name != 'cpu_idle') {
-            seriesArray.push(series);
+          var s = this.transformData(seriesData, displayName);
+          if ('CPU Idle' == s.name) {
+            cpu_idle = s;
           }
           else {
-            cpu_idle = series;
+            seriesArray.push(s);
           }
         }
       }

+ 13 - 20
ambari-web/app/views/main/host/metrics/disk.js

@@ -32,14 +32,18 @@ App.ChartHostMetricsDisk = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/disk/disk_total[{fromSeconds},{toSeconds},{stepSeconds}],metrics/disk/disk_free[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/disk.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/disk/disk_total[{fromSeconds},{toSeconds},{stepSeconds}],metrics/disk/disk_free[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/disk.json"
+    );
+  }.property('clusterName').volatile(),
 
   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;
@@ -58,22 +62,11 @@ App.ChartHostMetricsDisk = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
+          var s = this.transformData(seriesData, displayName);
+          for (var i = 0; i < s.data.length; i++) {
+            s.data[i].y *= GB;
           }
-          // We have valid data
-          var GB = Math.pow(2, 30);
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0] * GB
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(s);
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/host/metrics/load.js

@@ -31,11 +31,14 @@ App.ChartHostMetricsLoad = App.ChartLinearTimeView.extend({
   title: "Load",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/load/load_fifteen[{fromSeconds},{toSeconds},{stepSeconds}],metrics/load/load_one[{fromSeconds},{toSeconds},{stepSeconds}],metrics/load/load_five[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/load.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/load/load_fifteen[{fromSeconds},{toSeconds},{stepSeconds}],metrics/load/load_one[{fromSeconds},{toSeconds},{stepSeconds}],metrics/load/load_five[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/load.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -57,21 +60,7 @@ App.ChartHostMetricsLoad = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 14 - 20
ambari-web/app/views/main/host/metrics/memory.js

@@ -32,14 +32,19 @@ App.ChartHostMetricsMemory = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/memory/swap_free[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_shared[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_free[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_cached[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_buffers[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/memory.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/memory/swap_free[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_shared[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_free[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_cached[{fromSeconds},{toSeconds},{stepSeconds}],metrics/memory/mem_buffers[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        clusterName: this.get('clusterName'),
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/memory.json"
+    );
+  }.property('clusterName').volatile(),
 
   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;
@@ -64,22 +69,11 @@ App.ChartHostMetricsMemory = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
+          var s = this.transformData(seriesData, displayName);
+          for (var i = 0; i < s.data.length; i++) {
+            s.data[i].y *= KB;
           }
-          // We have valid data
-          var KB = Math.pow(2,10);
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0] * KB
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(s);
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/host/metrics/network.js

@@ -32,11 +32,14 @@ App.ChartHostMetricsNetwork = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/network/bytes_in[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/bytes_out[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/pkts_in[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/pkts_out[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/network.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/network/bytes_in[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/bytes_out[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/pkts_in[{fromSeconds},{toSeconds},{stepSeconds}],metrics/network/pkts_out[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/network.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -61,21 +64,7 @@ App.ChartHostMetricsNetwork = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/host/metrics/processes.js

@@ -31,11 +31,14 @@ App.ChartHostMetricsProcesses = App.ChartLinearTimeView.extend({
   title: "Processes",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}?fields=metrics/process/proc_total[{fromSeconds},{toSeconds},{stepSeconds}],metrics/process/proc_run[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: this.get('content').get('hostName')
-    }, "/data/hosts/metrics/processes.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}?fields=metrics/process/proc_total[{fromSeconds},{toSeconds},{stepSeconds}],metrics/process/proc_run[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: this.get('content').get('hostName')
+      },
+      "/data/hosts/metrics/processes.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +57,7 @@ App.ChartHostMetricsProcesses = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/cluster_requests.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsHBASE_ClusterRequests = App.ChartLinearTimeView.extend({
   title: "Cluster Requests",
 
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/cluster_requests[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/cluster_requests.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/cluster_requests[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/cluster_requests.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -50,21 +52,7 @@ App.ChartServiceMetricsHBASE_ClusterRequests = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/hlog_split_size.js

@@ -32,10 +32,12 @@ App.ChartServiceMetricsHBASE_HlogSplitSize = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
 
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/splitSize_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/hlog_split_size.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/splitSize_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/hlog_split_size.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -51,21 +53,7 @@ App.ChartServiceMetricsHBASE_HlogSplitSize = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/hlog_split_time.js

@@ -32,10 +32,12 @@ App.ChartServiceMetricsHBASE_HlogSplitTime = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.TimeElapsedFormatter,
 
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/splitTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/hlog_split_time.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_MASTER?fields=metrics/hbase/master/splitTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/hlog_split_time.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -51,21 +53,7 @@ App.ChartServiceMetricsHBASE_HlogSplitTime = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/regionserver_queuesize.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsHBASE_RegionServerQueueSize = App.ChartLinearTimeView.ext
   title: "RegionServer Queue Size",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/flushQueueSize[{fromSeconds},{toSeconds},{stepSeconds}],metrics/hbase/regionserver/compactionQueueSize[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/regionserver_queuesize.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/flushQueueSize[{fromSeconds},{toSeconds},{stepSeconds}],metrics/hbase/regionserver/compactionQueueSize[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/regionserver_queuesize.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -53,21 +55,7 @@ App.ChartServiceMetricsHBASE_RegionServerQueueSize = App.ChartLinearTimeView.ext
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/regionserver_regions.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsHBASE_RegionServerRegions = App.ChartLinearTimeView.exten
   title: "RegionServer Regions",
 
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/regions[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/regionserver_regions.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/regions[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/regionserver_regions.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -50,21 +52,7 @@ App.ChartServiceMetricsHBASE_RegionServerRegions = App.ChartLinearTimeView.exten
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hbase/regionserver_rw_requests.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsHBASE_RegionServerReadWriteRequests = App.ChartLinearTime
   title: "RegionServer Requests",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/readRequestsCount[{fromSeconds},{toSeconds},{stepSeconds}],metrics/hbase/regionserver/writeRequestsCount[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hbase/regionserver_rw_requests.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HBASE/components/HBASE_REGIONSERVER?fields=metrics/hbase/regionserver/readRequestsCount[{fromSeconds},{toSeconds},{stepSeconds}],metrics/hbase/regionserver/writeRequestsCount[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hbase/regionserver_rw_requests.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -53,21 +55,7 @@ App.ChartServiceMetricsHBASE_RegionServerReadWriteRequests = App.ChartLinearTime
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/block_status.js

@@ -33,11 +33,14 @@ App.ChartServiceMetricsHDFS_BlockStatus = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/FSNamesystem/PendingReplicationBlocks[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/UnderReplicatedBlocks[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/block_status.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/FSNamesystem/PendingReplicationBlocks[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/UnderReplicatedBlocks[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/block_status.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -56,21 +59,7 @@ App.ChartServiceMetricsHDFS_BlockStatus = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/file_operations.js

@@ -33,11 +33,14 @@ App.ChartServiceMetricsHDFS_FileOperations = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/namenode/FileInfoOps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/namenode/CreateFileOps[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/file_operations.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/namenode/FileInfoOps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/namenode/CreateFileOps[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/file_operations.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -59,21 +62,7 @@ App.ChartServiceMetricsHDFS_FileOperations = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/gc.js

@@ -34,11 +34,14 @@ App.ChartServiceMetricsHDFS_GC = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/gcTimeMillis[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/gc.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/gcTimeMillis[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/gc.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +57,7 @@ App.ChartServiceMetricsHDFS_GC = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/hdfs/io.js

@@ -32,10 +32,12 @@ App.ChartServiceMetricsHDFS_IO = App.ChartLinearTimeView.extend({
   yAxisFormatter: App.ChartLinearTimeView.BytesFormatter,
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/HDFS/components/DATANODE?fields=metrics/dfs/datanode/bytes_written[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/datanode/bytes_read[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/hdfs/io.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/HDFS/components/DATANODE?fields=metrics/dfs/datanode/bytes_written[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/datanode/bytes_read[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/hdfs/io.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +56,7 @@ App.ChartServiceMetricsHDFS_IO = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 13 - 21
ambari-web/app/views/main/service/info/metrics/hdfs/jvm_heap.js

@@ -34,14 +34,18 @@ App.ChartServiceMetricsHDFS_JVMHeap = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/memNonHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memNonHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/jvm_heap.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/memNonHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memNonHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/jvm_heap.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
+    var MB = Math.pow(2, 20);
     if (jsonData && jsonData.metrics && jsonData.metrics.jvm) {
       for ( var name in jsonData.metrics.jvm) {
         var displayName;
@@ -63,23 +67,11 @@ App.ChartServiceMetricsHDFS_JVMHeap = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
+          var s = this.transformData(seriesData, displayName);
+          for (var i = 0; i < s.data.length; i++) {
+            s.data[i].y *= MB;
           }
-          // We have valid data
-          var MB = Math.pow(2,20);
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0] * MB
-            // Data is in MB
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(s);
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/jvm_threads.js

@@ -33,11 +33,14 @@ App.ChartServiceMetricsHDFS_JVMThreads = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/threadsRunnable[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsBlocked[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsWaiting[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsTimedWaiting[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/jvm_threads.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/jvm/threadsRunnable[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsBlocked[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsWaiting[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsTimedWaiting[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/jvm_threads.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -62,21 +65,7 @@ App.ChartServiceMetricsHDFS_JVMThreads = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/rpc.js

@@ -34,11 +34,14 @@ App.ChartServiceMetricsHDFS_RPC = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/rpc/RpcQueueTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/rpc.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/rpc/RpcQueueTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/rpc.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +57,7 @@ App.ChartServiceMetricsHDFS_RPC = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 13 - 20
ambari-web/app/views/main/service/info/metrics/hdfs/space_utilization.js

@@ -34,14 +34,18 @@ App.ChartServiceMetricsHDFS_SpaceUtilization = App.ChartLinearTimeView.extend({
   url: function () {
     var hdfsService = App.HDFSService.find().objectAt(0);
     var nameNodeHostName = hdfsService.get('nameNode').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/FSNamesystem/CapacityRemainingGB[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/CapacityUsedGB[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/CapacityTotalGB[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: nameNodeHostName
-    }, "/data/services/metrics/hdfs/space_utilization.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/NAMENODE?fields=metrics/dfs/FSNamesystem/CapacityRemainingGB[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/CapacityUsedGB[{fromSeconds},{toSeconds},{stepSeconds}],metrics/dfs/FSNamesystem/CapacityTotalGB[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: nameNodeHostName
+      },
+      "/data/services/metrics/hdfs/space_utilization.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
+    var GB = Math.pow(2, 30);
     if (jsonData && jsonData.metrics && jsonData.metrics.dfs && jsonData.metrics.dfs.FSNamesystem) {
       for ( var name in jsonData.metrics.dfs.FSNamesystem) {
         var displayName;
@@ -60,22 +64,11 @@ App.ChartServiceMetricsHDFS_SpaceUtilization = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
+          var s = this.transformData(seriesData, displayName);
+          for (var i = 0; i < s.data.length; i++) {
+            s.data[i].y *= GB;
           }
-          // We have valid data
-          var GB = Math.pow(2,30);
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]*GB
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(s);
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/mapreduce/gc.js

@@ -34,11 +34,14 @@ App.ChartServiceMetricsMapReduce_GC = App.ChartLinearTimeView.extend({
   url: function () {
     var mrService = App.MapReduceService.find().objectAt(0);
     var jtHostName = mrService.get('jobTracker').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/gcTimeMillis[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: jtHostName
-    }, "/data/services/metrics/mapreduce/gc.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/gcTimeMillis[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: jtHostName
+      },
+      "/data/services/metrics/mapreduce/gc.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +57,7 @@ App.ChartServiceMetricsMapReduce_GC = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/mapreduce/jobs_status.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsMapReduce_JobsStatus = App.ChartLinearTimeView.extend({
   title: "Jobs Status",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/jobs_completed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_preparing[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_failed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_submitted[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_failed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_running[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/mapreduce/jobs_status.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/jobs_completed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_preparing[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_failed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_submitted[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_failed[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/jobs_running[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/mapreduce/jobs_status.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -62,21 +64,7 @@ App.ChartServiceMetricsMapReduce_JobsStatus = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 13 - 21
ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_heap.js

@@ -34,14 +34,18 @@ App.ChartServiceMetricsMapReduce_JVMHeap = App.ChartLinearTimeView.extend({
   url: function () {
     var mrService = App.MapReduceService.find().objectAt(0);
     var jtHostName = mrService.get('jobTracker').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/memNonHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memNonHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: jtHostName
-    }, "/data/services/metrics/mapreduce/jvm_heap.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/memNonHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memNonHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapUsedM[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/memHeapCommittedM[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: jtHostName
+      },
+      "/data/services/metrics/mapreduce/jvm_heap.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
+    var MB = Math.pow(2, 20);
     if (jsonData && jsonData.metrics && jsonData.metrics.jvm) {
       for ( var name in jsonData.metrics.jvm) {
         var displayName;
@@ -63,23 +67,11 @@ App.ChartServiceMetricsMapReduce_JVMHeap = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
+          var s = this.transformData(seriesData, displayName);
+          for (var i = 0; i < s.data.length; i++) {
+            s.data[i].y *= MB;
           }
-          // We have valid data
-          var MB = Math.pow(2, 20);
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0] * MB
-            // Data is in MB
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(s);
         }
       }
     }

+ 10 - 20
ambari-web/app/views/main/service/info/metrics/mapreduce/jvm_threads.js

@@ -33,11 +33,14 @@ App.ChartServiceMetricsMapReduce_JVMThreads = App.ChartLinearTimeView.extend({
   url: function () {
     var mrService = App.MapReduceService.find().objectAt(0);
     var jtHostName = mrService.get('jobTracker').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/threadsRunnable[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsBlocked[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsWaiting[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsTimedWaiting[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: jtHostName
-    }, "/data/services/metrics/mapreduce/jvm_threads.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/jvm/threadsRunnable[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsBlocked[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsWaiting[{fromSeconds},{toSeconds},{stepSeconds}],metrics/jvm/threadsTimedWaiting[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: jtHostName
+      },
+      "/data/services/metrics/mapreduce/jvm_threads.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -61,22 +64,9 @@ App.ChartServiceMetricsMapReduce_JVMThreads = App.ChartLinearTimeView.extend({
           default:
             break;
         }
+
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/mapreduce/map_slots.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsMapReduce_MapSlots = App.ChartLinearTimeView.extend({
   title: "Map Slots Utilization",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/occupied_map_slots[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/reserved_map_slots[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/mapreduce/map_slots.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/occupied_map_slots[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/reserved_map_slots[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/mapreduce/map_slots.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -53,21 +55,7 @@ App.ChartServiceMetricsMapReduce_MapSlots = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/mapreduce/reduce_slots.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsMapReduce_ReduceSlots = App.ChartLinearTimeView.extend({
   title: "Reduce Slots Utilization",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/occupied_reduce_slots[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/reserved_reduce_slots[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/mapreduce/reduce_slots.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/occupied_reduce_slots[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/reserved_reduce_slots[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/mapreduce/reduce_slots.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -53,21 +55,7 @@ App.ChartServiceMetricsMapReduce_ReduceSlots = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 9 - 20
ambari-web/app/views/main/service/info/metrics/mapreduce/rpc.js

@@ -34,11 +34,14 @@ App.ChartServiceMetricsMapReduce_RPC = App.ChartLinearTimeView.extend({
   url: function () {
     var mrService = App.MapReduceService.find().objectAt(0);
     var jtHostName = mrService.get('jobTracker').get('hostName');
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/rpc/RpcQueueTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName'),
-      hostName: jtHostName
-    }, "/data/services/metrics/mapreduce/rpc.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/hosts/{hostName}/host_components/JOBTRACKER?fields=metrics/rpc/RpcQueueTime_avg_time[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {
+        hostName: jtHostName
+      },
+      "/data/services/metrics/mapreduce/rpc.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -54,21 +57,7 @@ App.ChartServiceMetricsMapReduce_RPC = App.ChartLinearTimeView.extend({
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }

+ 7 - 19
ambari-web/app/views/main/service/info/metrics/mapreduce/tasks_running_waiting.js

@@ -31,10 +31,12 @@ App.ChartServiceMetricsMapReduce_TasksRunningWaiting = App.ChartLinearTimeView.e
   title: "Tasks (Running/Waiting)",
   renderer: 'line',
   url: function () {
-    return App.formatUrl(App.apiPrefix + "/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/running_maps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/running_reduces[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/waiting_maps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/waiting_reduces[{fromSeconds},{toSeconds},{stepSeconds}]", {
-      clusterName: App.router.get('clusterController.clusterName')
-    }, "/data/services/metrics/mapreduce/tasks_running_waiting.json");
-  }.property('App.router.clusterController.clusterName').volatile(),
+    return App.formatUrl(
+      this.get('urlPrefix') + "/services/MAPREDUCE/components/JOBTRACKER?fields=metrics/mapred/jobtracker/running_maps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/running_reduces[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/waiting_maps[{fromSeconds},{toSeconds},{stepSeconds}],metrics/mapred/jobtracker/waiting_reduces[{fromSeconds},{toSeconds},{stepSeconds}]",
+      {},
+      "/data/services/metrics/mapreduce/tasks_running_waiting.json"
+    );
+  }.property('clusterName').volatile(),
 
   transformToSeries: function (jsonData) {
     var seriesArray = [];
@@ -59,21 +61,7 @@ App.ChartServiceMetricsMapReduce_TasksRunningWaiting = App.ChartLinearTimeView.e
             break;
         }
         if (seriesData) {
-          // Is it a string?
-          if ("string" == typeof seriesData) {
-            seriesData = JSON.parse(seriesData);
-          }
-          // We have valid data
-          var series = {};
-          series.name = displayName;
-          series.data = [];
-          for ( var index = 0; index < seriesData.length; index++) {
-            series.data.push({
-              x: seriesData[index][1],
-              y: seriesData[index][0]
-            });
-          }
-          seriesArray.push(series);
+          seriesArray.push(this.transformData(seriesData, displayName));
         }
       }
     }