You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ea...@apache.org on 2018/01/18 19:09:25 UTC

qpid-dispatch git commit: DISPATCH-904 Add charts to overview page

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 1198ceeff -> 7f1544098


DISPATCH-904 Add charts to overview page


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/7f154409
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/7f154409
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/7f154409

Branch: refs/heads/master
Commit: 7f15440980e4633e8bbf6af919ef187cf262e127
Parents: 1198cee
Author: Ernest Allen <ea...@redhat.com>
Authored: Thu Jan 18 14:09:03 2018 -0500
Committer: Ernest Allen <ea...@redhat.com>
Committed: Thu Jan 18 14:09:03 2018 -0500

----------------------------------------------------------------------
 console/stand-alone/index.html                  |   2 +
 console/stand-alone/plugin/css/dispatchpf.css   |  10 +
 .../stand-alone/plugin/html/qdrOverview.html    |  15 +-
 .../stand-alone/plugin/js/dlgChartController.js | 202 ++++++++++++++++
 console/stand-alone/plugin/js/navbar.js         | 175 --------------
 .../stand-alone/plugin/js/qdrChartService.js    | 124 ++++++----
 console/stand-alone/plugin/js/qdrList.js        |   8 +-
 console/stand-alone/plugin/js/qdrOverview.js    |  34 +--
 .../plugin/js/qdrOverviewChartsController.js    | 103 +++++++-
 .../plugin/js/qdrTopAddressesController.js      | 234 +++++++++++++++++++
 10 files changed, 658 insertions(+), 249 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/index.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/index.html b/console/stand-alone/index.html
index e696484..8519920 100644
--- a/console/stand-alone/index.html
+++ b/console/stand-alone/index.html
@@ -134,6 +134,8 @@ under the License.
 <script type="text/javascript" src="plugin/js/qdrOverview.js"></script>
 <script type="text/javascript" src="plugin/js/qdrOverviewLogsController.js"></script>
 <script type="text/javascript" src="plugin/js/qdrOverviewChartsController.js"></script>
+<script type="text/javascript" src="plugin/js/qdrTopAddressesController.js"></script>
+<script type="text/javascript" src="plugin/js/dlgChartController.js"></script>
 <script type="text/javascript" src="plugin/js/navbar.js"></script>
 <script type="text/javascript" src="plugin/js/qdrList.js"></script>
 <script type="text/javascript" src="plugin/js/qdrListChart.js"></script>

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/css/dispatchpf.css
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/css/dispatchpf.css b/console/stand-alone/plugin/css/dispatchpf.css
index 04ca1c2..c469d19 100644
--- a/console/stand-alone/plugin/css/dispatchpf.css
+++ b/console/stand-alone/plugin/css/dispatchpf.css
@@ -300,4 +300,14 @@ span.fancytree-expander {
 
 th.text-center {
   text-align: center;
+}
+
+.clearfix:after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+#topAddresses.grid {
+  min-height: 190px;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/html/qdrOverview.html
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/html/qdrOverview.html b/console/stand-alone/plugin/html/qdrOverview.html
index b086f93..b593c4a 100644
--- a/console/stand-alone/plugin/html/qdrOverview.html
+++ b/console/stand-alone/plugin/html/qdrOverview.html
@@ -22,10 +22,17 @@ under the License.
 </script>
 
 <script type="text/ng-template" id="overviewCharts.html">
-    <div ng-repeat="chart in overviewCharts" class="chartContainer" ng-controller="QDR.OverviewChartsController">
-        <p class="chartLabels">
-        </p><div style="clear:both"></div>
-        <div id="{{chart.chart.id()}}" class="line-chart-pf aChart d3Chart"></div>
+    <div ng-controller="QDR.OverviewChartsController" class="clearfix">
+        <div ng-repeat="chart in overviewCharts" class="chartContainer" >
+            <p class="chartLabels">
+            </p><div style="clear:both"></div>
+            <div id="{{chart.chart.id()}}" class="line-chart-pf aChart d3Chart"></div>
+        </div>
+    </div>
+    <div ng-controller="QDR.TopAddressesController">
+        <h1>Most active addresses</h1>
+        <div ng-if="anyAddresses()" id="topAddresses" class="grid" ui-grid="topAddressesGrid"  ui-grid-selection ui-grid-auto-resize ui-grid-resize-columns ui-grid-save-state></div>
+        <div ng-if="!anyAddresses()">There are no addresses to which messages are being delivered.</div>
     </div>
 </script>
 

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/dlgChartController.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/dlgChartController.js b/console/stand-alone/plugin/js/dlgChartController.js
new file mode 100644
index 0000000..1613cb6
--- /dev/null
+++ b/console/stand-alone/plugin/js/dlgChartController.js
@@ -0,0 +1,202 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function(QDR) {
+
+  // controller for the edit/configure chart dialog
+  QDR.module.controller("QDR.ChartDialogController", function($scope, QDRChartService, $location, $uibModalInstance, chart, updateTick, dashboard, adding) {
+    var dialogSvgChart = null;
+    $scope.svgDivId = "dialogEditChart";    // the div id for the svg chart
+
+    var updateTimer = null;
+    $scope.chart = chart;  // the underlying chart object from the dashboard
+    $scope.dialogChart = $scope.chart.copy(); // the chart object for this dialog
+    $scope.userTitle = $scope.chart.title();
+
+    $scope.$watch('userTitle', function(newValue, oldValue) {
+    if (newValue !== oldValue) {
+      $scope.dialogChart.title(newValue);
+      dialogSvgChart.tick($scope.svgDivId);
+    }
+    })
+    $scope.$watch("dialogChart.areaColor", function (newValue, oldValue) {
+      if (newValue !== oldValue) {
+        if (dialogSvgChart)
+         dialogSvgChart.tick($scope.svgDivId);
+      }
+    })
+    $scope.$watch("dialogChart.lineColor", function (newValue, oldValue) {
+      if (newValue !== oldValue) {
+        if (dialogSvgChart)
+          dialogSvgChart.tick($scope.svgDivId);
+      }
+    })
+    $scope.$watch("dialogChart.type", function (newValue, oldValue) {
+      if (newValue !== oldValue) {
+        if (dialogSvgChart) {
+          dialogSvgChart.chart.visibleDuration = newValue === 'rate' ? 0.25 : 1
+          dialogSvgChart.tick($scope.svgDivId);
+        }
+      }
+    })
+
+    // the stored rateWindow is in milliseconds, but the slider is in seconds
+    $scope.rateWindow = $scope.chart.rateWindow / 1000;
+
+    $scope.addChartsPage = function () {
+      QDRChartService.addDashboard(dialogSvgChart.chart);
+    };
+    $scope.delChartsPage = function () {
+      QDRChartService.delDashboard($scope.chart);
+    }
+
+    $scope.showChartsPage = function () {
+      cleanup();
+      $uibModalInstance.close(true);
+      $location.path(QDR.pluginRoot + "/charts");
+    };
+
+    var cleanup = function () {
+      if (updateTimer) {
+        clearTimeout(updateTimer);
+        updateTimer = null;
+      }
+      if (!$scope.isOnChartsPage())
+        QDRChartService.unRegisterChart($scope.dialogChart);     // remove the chart
+    }
+    $scope.okClick = function () {
+      cleanup();
+      $uibModalInstance.close(true);
+    };
+
+    var initRateSlider = function () {
+      if (document.getElementById('rateSlider')) {
+        $( "#rateSlider" ).slider({
+          value: $scope.rateWindow,
+          min: 1,
+          max: 10,
+          step: 1,
+          slide: function( event, ui ) {
+            $scope.rateWindow = ui.value;
+            $scope.dialogChart.rateWindow = ui.value * 1000;
+            $scope.$apply();
+            if (dialogSvgChart)
+              dialogSvgChart.tick($scope.svgDivId);
+          }
+        });
+      } else {
+        setTimeout(initRateSlider, 100)
+      }
+    }
+    //initRateSlider();
+
+    var initDurationSlider = function () {
+      if (document.getElementById('durationSlider')) {
+        $( "#durationSlider" ).slider({
+          value: $scope.dialogChart.visibleDuration,
+          min: 0.25,
+          max: 10,
+          step: 0.25,
+          slide: function( event, ui ) {
+            $scope.visibleDuration = $scope.dialogChart.visibleDuration = ui.value;
+            $scope.$apply();
+            if (dialogSvgChart)
+              dialogSvgChart.tick($scope.svgDivId);
+          }
+        });
+      } else {
+        setTimeout(initDurationSlider, 100)
+      }
+    }
+    initDurationSlider();
+
+    $scope.adding = function () {
+      return adding
+    }
+
+    $scope.isOnChartsPage = function () {
+      var chart = $scope.chart
+      if (adding)
+        return QDRChartService.isAttrCharted(chart.nodeId(), chart.entity(), chart.name(), chart.attr(), chart.aggregate())
+      else
+        return $scope.chart.dashboard
+    }
+
+    // handle the Apply button click
+    // update the dashboard chart's properties
+    $scope.apply = function () {
+      $scope.chart.areaColor = $scope.dialogChart.areaColor;
+      $scope.chart.lineColor = $scope.dialogChart.lineColor;
+      $scope.chart.type = $scope.dialogChart.type;
+      $scope.chart.rateWindow = $scope.rateWindow * 1000;
+      $scope.chart.title($scope.dialogChart.title());
+      $scope.chart.visibleDuration = $scope.dialogChart.visibleDuration;
+      QDRChartService.saveCharts();
+      if (typeof updateTick === "function")
+        updateTick();
+    }
+
+    // add a new chart to the dashboard based on the current dialog settings
+    $scope.copyToDashboard = function () {
+        var chart = $scope.dialogChart.copy();
+        // set the new chart's dashboard state
+        QDRChartService.addDashboard(chart);
+        // notify the chart controller that it needs to display a new chart
+        dashboard.addChart(chart);
+    }
+
+    // update the chart on the popup dialog
+    var updateDialogChart = function () {
+      // draw the chart using the current data
+      if (dialogSvgChart)
+          dialogSvgChart.tick($scope.svgDivId);
+
+      // draw the chart again in 1 second
+      var updateRate = localStorage['updateRate'] ? localStorage['updateRate'] : 1000;
+      if (updateTimer)
+      clearTimeout(updateTimer);
+        updateTimer = setTimeout(updateDialogChart, updateRate);
+    }
+
+    var showChart = function () {
+      // ensure the div for our chart is loaded in the dom
+      var div = angular.element("#" + $scope.svgDivId);
+      if (!div.width()) {
+        setTimeout(showChart, 100);
+        return;
+      }
+      dialogSvgChart = new QDRChartService.pfAreaChart($scope.dialogChart, $scope.svgDivId)
+/*
+      $('input[name=areaColor]').val($scope.dialogChart.areaColor);
+      $('input[name=areaColor]').on('input', function (e) {
+        $scope.dialogChart.areaColor = $(this).val();
+        updateDialogChart()
+      })
+*/
+      if (updateTimer)
+        clearTimeout(updateTimer);
+          updateDialogChart();
+    }
+    showChart();
+  });
+  return QDR;
+
+} (QDR || {}));

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/navbar.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/navbar.js b/console/stand-alone/plugin/js/navbar.js
index 7cb129a..1829352 100644
--- a/console/stand-alone/plugin/js/navbar.js
+++ b/console/stand-alone/plugin/js/navbar.js
@@ -117,181 +117,6 @@ var QDR = (function (QDR) {
 
   }]);
 
-  // controller for the edit/configure chart dialog
-  QDR.module.controller("QDR.ChartDialogController", function($scope, QDRChartService, $location, $uibModalInstance, chart, updateTick, dashboard, adding) {
-    var dialogSvgChart = null;
-    $scope.svgDivId = "dialogEditChart";    // the div id for the svg chart
-
-    var updateTimer = null;
-    $scope.chart = chart;  // the underlying chart object from the dashboard
-    $scope.dialogChart = $scope.chart.copy(); // the chart object for this dialog
-    $scope.userTitle = $scope.chart.title();
-
-    $scope.$watch('userTitle', function(newValue, oldValue) {
-    if (newValue !== oldValue) {
-      $scope.dialogChart.title(newValue);
-      dialogSvgChart.tick($scope.svgDivId);
-    }
-    })
-    $scope.$watch("dialogChart.areaColor", function (newValue, oldValue) {
-      if (newValue !== oldValue) {
-        if (dialogSvgChart)
-         dialogSvgChart.tick($scope.svgDivId);
-      }
-    })
-    $scope.$watch("dialogChart.lineColor", function (newValue, oldValue) {
-      if (newValue !== oldValue) {
-        if (dialogSvgChart)
-          dialogSvgChart.tick($scope.svgDivId);
-      }
-    })
-    $scope.$watch("dialogChart.type", function (newValue, oldValue) {
-      if (newValue !== oldValue) {
-        if (dialogSvgChart)
-          dialogSvgChart.tick($scope.svgDivId);
-      }
-    })
-
-    // the stored rateWindow is in milliseconds, but the slider is in seconds
-    $scope.rateWindow = $scope.chart.rateWindow / 1000;
-
-    $scope.addChartsPage = function () {
-      QDRChartService.addDashboard(dialogSvgChart.chart);
-    };
-    $scope.delChartsPage = function () {
-      QDRChartService.delDashboard($scope.chart);
-    }
-
-    $scope.showChartsPage = function () {
-      cleanup();
-      $uibModalInstance.close(true);
-      $location.path(QDR.pluginRoot + "/charts");
-    };
-
-    var cleanup = function () {
-      if (updateTimer) {
-        clearTimeout(updateTimer);
-        updateTimer = null;
-      }
-      if (!$scope.isOnChartsPage())
-        QDRChartService.unRegisterChart($scope.dialogChart);     // remove the chart
-    }
-    $scope.okClick = function () {
-      cleanup();
-      $uibModalInstance.close(true);
-    };
-
-    var initRateSlider = function () {
-      if (document.getElementById('rateSlider')) {
-        $( "#rateSlider" ).slider({
-          value: $scope.rateWindow,
-          min: 1,
-          max: 10,
-          step: 1,
-          slide: function( event, ui ) {
-            $scope.rateWindow = ui.value;
-            $scope.dialogChart.rateWindow = ui.value * 1000;
-            $scope.$apply();
-            if (dialogSvgChart)
-              dialogSvgChart.tick($scope.svgDivId);
-          }
-        });
-      } else {
-        setTimeout(initRateSlider, 100)
-      }
-    }
-    //initRateSlider();
-
-    var initDurationSlider = function () {
-      if (document.getElementById('durationSlider')) {
-        $( "#durationSlider" ).slider({
-          value: $scope.dialogChart.visibleDuration,
-          min: 1,
-          max: 10,
-          step: 1,
-          slide: function( event, ui ) {
-            $scope.visibleDuration = $scope.dialogChart.visibleDuration = ui.value;
-            $scope.$apply();
-            if (dialogSvgChart)
-              dialogSvgChart.tick($scope.svgDivId);
-          }
-        });
-      } else {
-        setTimeout(initDurationSlider, 100)
-      }
-    }
-    initDurationSlider();
-
-    $scope.adding = function () {
-      return adding
-    }
-
-    $scope.isOnChartsPage = function () {
-      var chart = $scope.chart
-      if (adding)
-        return QDRChartService.isAttrCharted(chart.nodeId(), chart.entity(), chart.name(), chart.attr(), chart.aggregate())
-      else
-        return $scope.chart.dashboard
-    }
-
-    // handle the Apply button click
-    // update the dashboard chart's properties
-    $scope.apply = function () {
-      $scope.chart.areaColor = $scope.dialogChart.areaColor;
-      $scope.chart.lineColor = $scope.dialogChart.lineColor;
-      $scope.chart.type = $scope.dialogChart.type;
-      $scope.chart.rateWindow = $scope.rateWindow * 1000;
-      $scope.chart.title($scope.dialogChart.title());
-      $scope.chart.visibleDuration = $scope.dialogChart.visibleDuration;
-      QDRChartService.saveCharts();
-      if (typeof updateTick === "function")
-        updateTick();
-    }
-
-    // add a new chart to the dashboard based on the current dialog settings
-    $scope.copyToDashboard = function () {
-        var chart = $scope.dialogChart.copy();
-        // set the new chart's dashboard state
-        QDRChartService.addDashboard(chart);
-        // notify the chart controller that it needs to display a new chart
-        dashboard.addChart(chart);
-    }
-
-    // update the chart on the popup dialog
-    var updateDialogChart = function () {
-      // draw the chart using the current data
-      if (dialogSvgChart)
-          dialogSvgChart.tick($scope.svgDivId);
-
-      // draw the chart again in 1 second
-      var updateRate = localStorage['updateRate'] ? localStorage['updateRate'] : 1000;
-      if (updateTimer)
-      clearTimeout(updateTimer);
-        updateTimer = setTimeout(updateDialogChart, updateRate);
-    }
-
-    var showChart = function () {
-      // ensure the div for our chart is loaded in the dom
-      var div = angular.element("#" + $scope.svgDivId);
-      if (!div.width()) {
-        setTimeout(showChart, 100);
-        return;
-      }
-      dialogSvgChart = new QDRChartService.pfAreaChart($scope.dialogChart, $scope.svgDivId)
-/*
-      $('input[name=areaColor]').val($scope.dialogChart.areaColor);
-      $('input[name=areaColor]').on('input', function (e) {
-        $scope.dialogChart.areaColor = $(this).val();
-        updateDialogChart()
-      })
-*/
-      if (updateTimer)
-        clearTimeout(updateTimer);
-          updateDialogChart();
-    }
-    showChart();
-  });
-
   return QDR;
 
 } (QDR || {}));

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/qdrChartService.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrChartService.js b/console/stand-alone/plugin/js/qdrChartService.js
index 51b033f..a0f5343 100644
--- a/console/stand-alone/plugin/js/qdrChartService.js
+++ b/console/stand-alone/plugin/js/qdrChartService.js
@@ -72,8 +72,10 @@ var QDR = (function(QDR) {
         this.rateWindow = opts.rateWindow ? opts.rateWindow : 1000; // calculate the rate of change over this time interval. higher == smother graph
         this.areaColor = "#32b9f3"; // the chart's area color when not an empty string
         this.lineColor = "#058dc7"; // the chart's line color when not an empty string
-        this.visibleDuration = opts.visibleDuration ? opts.visibleDuration : 1; // number of minutes of data to show (<= base.duration)
+        this.visibleDuration = opts.visibleDuration ? opts.visibleDuration : opts.type === 'rate' ? 0.25 : 1; // number of minutes of data to show (<= base.duration)
         this.userTitle = null; // user title overrides title()
+        this.hideLabel = opts.hideLabel
+        this.hideLegend = opts.hideLegend
 
         // generate a unique id for this chart
         this.id = function() {
@@ -203,7 +205,10 @@ var QDR = (function(QDR) {
 
         this.interval = opts.interval || 1000; // number of milliseconds between updates to data
         this.setTimeoutHandle = null; // used to cancel the next request
-        // copy the savable properties to an object
+
+        // allow override of normal request's management call to get data
+        this.override = opts.override; // call this instead of internal function to retreive data
+        this.overrideAttrs = opts.overrideAttrs //
 
         this.data = function(name, attr) {
           if (this.datum[name] && this.datum[name][attr])
@@ -330,6 +335,22 @@ var QDR = (function(QDR) {
           }
         },
 
+        createChart: function (opts, request) {
+          return new Chart(opts, request)
+        },
+        createChartRequest: function (opts) {
+          var request = new ChartRequest(opts); //nodeId, entity, name, attr, interval, aggregate);
+          request.creationTimestamp = opts.now
+          self.chartRequests.push(request);
+          self.startCollecting(request);
+          self.sendChartRequest(request, true)
+          return request;
+        },
+        destroyChartRequest: function (request) {
+          self.stopCollecting(request);
+          self.delChartRequest(request);
+        },
+
         registerChart: function(opts) { //nodeId, entity, name, attr, interval, instance, forceCreate, aggregate, hdash) {
           var request = self.findChartRequest(opts.nodeId, opts.entity, opts.aggregate);
           if (request) {
@@ -338,10 +359,7 @@ var QDR = (function(QDR) {
           } else {
             // the nodeId/entity did not already exist, so add a new request and chart
             QDR.log.debug("added new request: " + opts.nodeId + " " + opts.entity);
-            request = new ChartRequest(opts); //nodeId, entity, name, attr, interval, aggregate);
-            self.chartRequests.push(request);
-            self.startCollecting(request);
-            self.sendChartRequest(request, true)
+            var request = self.createChartRequest(opts);
           }
           var charts = self.findCharts(opts); //name, attr, nodeId, entity, hdash);
           var chart;
@@ -384,8 +402,7 @@ var QDR = (function(QDR) {
                 }
                 // no other charts use this attr, so remove it
                 if (request.removeAttr(chart.name(), chart.attr()) == 0) {
-                  self.stopCollecting(request);
-                  self.delChartRequest(request);
+                  self.destroyChartRequest(request)
                 }
               }
             }
@@ -396,14 +413,13 @@ var QDR = (function(QDR) {
 
         stopCollecting: function(request) {
           if (request.setTimeoutHandle) {
-            clearTimeout(request.setTimeoutHandle);
+            clearInterval(request.setTimeoutHandle);
             request.setTimeoutHandle = null;
           }
         },
 
         startCollecting: function(request) {
-          // Using setTimeout instead of setInterval because the response may take longer than interval
-          request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request);
+          request.setTimeoutHandle = setInterval(self.sendChartRequest, request.interval, request);
         },
         shouldRequest: function(request) {
           // see if any of the charts associated with this request have either dialog, dashboard, or hreq
@@ -413,11 +429,13 @@ var QDR = (function(QDR) {
         },
         // send the request
         sendChartRequest: function(request, once) {
-          if (!once && !self.shouldRequest(request)) {
-            request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request)
+          //if (!once)
+          //  request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request)
+          if (request.busy)
+            return
+          if (self.charts.length > 0 && !self.shouldRequest(request)) {
             return;
           }
-
           // ensure the response has the name field so we can associate the response values with the correct chart
           var attrs = request.attrs();
           if (attrs.indexOf("name") == -1)
@@ -425,6 +443,7 @@ var QDR = (function(QDR) {
 
           // this is called when the response is received
           var saveResponse = function(nodeId, entity, response) {
+            request.busy = false
             if (!response || !response.attributeNames)
               return;
             //QDR.log.debug("got chart results for " + nodeId + " " + entity);
@@ -447,33 +466,39 @@ var QDR = (function(QDR) {
               // if we want to store the values for some attrs for this name
               if (names.indexOf(name) > -1) {
                 attrs.forEach(function(attr) {
-                  var data = request.data(name, attr) // get a reference to the data array
-                  if (data) {
-                    var attrIndex = response.attributeNames.indexOf(attr)
-                    if (request.aggregate) {
-                      data.push([now, response.aggregates[i][attrIndex].sum, response.aggregates[i][attrIndex].detail])
-                    } else {
-                      data.push([now, records[i][attrIndex]])
-                    }
-                    // expire the old data
-                    while (data[0][0] < cutOff) {
-                      data.shift();
+                  var attrIndex = response.attributeNames.indexOf(attr)
+                  if (records[i][attrIndex] !== undefined) {
+                    var data = request.data(name, attr) // get a reference to the data array
+                    if (data) {
+
+                      if (request.aggregate) {
+                        data.push([now, response.aggregates[i][attrIndex].sum, response.aggregates[i][attrIndex].detail])
+                      } else {
+                        data.push([now, records[i][attrIndex]])
+                      }
+                      // expire the old data
+                      while (data[0][0] < cutOff) {
+                        data.shift();
+                      }
                     }
                   }
                 })
               }
             }
           }
-          if (request.aggregate) {
-            var nodeList = QDRService.management.topology.nodeIdList()
-            QDRService.management.topology.getMultipleNodeInfo(nodeList, request.entity, attrs, saveResponse, request.nodeId);
+          request.busy = true
+          // check for override of request
+          if (request.override) {
+            request.override(request, saveResponse)
           } else {
-            QDRService.management.topology.fetchEntity(request.nodeId, request.entity, attrs, saveResponse);
+            // send the appropriate request
+            if (request.aggregate) {
+              var nodeList = QDRService.management.topology.nodeIdList()
+              QDRService.management.topology.getMultipleNodeInfo(nodeList, request.entity, attrs, saveResponse, request.nodeId);
+            } else {
+              QDRService.management.topology.fetchEntity(request.nodeId, request.entity, attrs, saveResponse);
+            }
           }
-          // it is now safe to schedule another request
-          if (once)
-            return;
-          request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request)
         },
 
         numCharts: function() {
@@ -563,7 +588,7 @@ var QDR = (function(QDR) {
                 newChart.areaColor = chart.areaColor ? chart.areaColor : "#32b9f3";
                 newChart.lineColor = chart.lineColor ? chart.lineColor : "#058dc7";
                 newChart.duration(chart.duration);
-                newChart.visibleDuration = chart.visibleDuration ? chart.visibleDuration : 1;
+                newChart.visibleDuration = chart.visibleDuration ? chart.visibleDuration : newChart.type === 'rate' ? 0.25 : 1;
                 if (chart.userTitle)
                   newChart.title(chart.userTitle);
               }
@@ -648,10 +673,7 @@ var QDR = (function(QDR) {
                 return d3.timeFormat("%M:%S")(d)
               }).bind(this),
               culling: {max: 4}
-            },
-            label: {
-              text: chart.name()
-        }
+            }
           },
           y: {
             tick: {
@@ -660,6 +682,14 @@ var QDR = (function(QDR) {
             }
           }
         }
+
+        if (!chart.hideLabel) {
+            singleAreaChartConfig.axis.x.label = {
+              text: chart.name(),
+              position: 'outer-right'
+            }
+
+        }
         singleAreaChartConfig.transition = {
           duration: 0
         }
@@ -707,7 +737,17 @@ var QDR = (function(QDR) {
           return i >= 0 ? this.colors[i % 10] : color
         }).bind(this)
 
-        singleAreaChartConfig.legend = {show: true}
+        if (!chart.hideLegend) {
+          singleAreaChartConfig.legend = {
+            show: true,
+          }
+        }
+
+        if (this.stacked) {
+          // create a stacked area chart
+          singleAreaChartConfig.data.groups = [QDRService.management.topology.nodeNameList()]
+          singleAreaChartConfig.data.order = function (t1, t2) { return t1.id < t2.id }
+        }
 
         this.singleAreaChart = c3.generate(singleAreaChartConfig);
       }
@@ -799,12 +839,6 @@ var QDR = (function(QDR) {
           rate = ' per second'
         d3.select("#"+this.htmlId+" svg text.c3-title").text(QDRService.utilities.humanify(this.chart.attr()) + rate);
 
-/*
-        var type='area'
-        if (this.chart.type === 'rate')
-          type = 'area-spline'
-        this.singleAreaChart.transform(type);
-*/
         var d = this.chartData()
         // load the new data
         // using the c3.flow api causes the x-axis labels to jump around

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/qdrList.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrList.js b/console/stand-alone/plugin/js/qdrList.js
index 7263da8..3cd3430 100644
--- a/console/stand-alone/plugin/js/qdrList.js
+++ b/console/stand-alone/plugin/js/qdrList.js
@@ -508,7 +508,7 @@ var QDR = (function(QDR) {
     $scope.selectNode = function(node) {
       $scope.selectedNode = node.name;
       $scope.selectedNodeId = node.id;
-      setCurrentNode();
+      $timeout(setCurrentNode);
     };
     $scope.$watch('ActivatedKey', function(newValue, oldValue) {
       if (newValue !== oldValue) {
@@ -601,8 +601,8 @@ var QDR = (function(QDR) {
       }
       // if this entity should show an aggregate column, send the request to get the info for this entity from all the nedes
       if (aggregateEntities.indexOf(entity) > -1) {
-        var nodeInfo = QDRService.management.topology.nodeInfo();
-        QDRService.management.topology.getMultipleNodeInfo(Object.keys(nodeInfo), entity, [], gotNodeInfo, $scope.selectedNodeId);
+        var nodeIdList = QDRService.management.topology.nodeIdList();
+        QDRService.management.topology.getMultipleNodeInfo(nodeIdList, entity, [], gotNodeInfo, $scope.selectedNodeId);
       } else {
         QDRService.management.topology.fetchEntity($scope.selectedNodeId, entity, [], gotNodeInfo);
       }
@@ -634,7 +634,7 @@ var QDR = (function(QDR) {
         attr:       rowEntity.name,
         type:       "rate",
         rateWindow: updateInterval,
-        visibleDuration: 1,
+        visibleDuration: 0.25,
         forceCreate: true,
         aggregate:   true});
       doDialog('tmplChartConfig.html', chart);

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/qdrOverview.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrOverview.js b/console/stand-alone/plugin/js/qdrOverview.js
index 9e8f565..7f2a71c 100644
--- a/console/stand-alone/plugin/js/qdrOverview.js
+++ b/console/stand-alone/plugin/js/qdrOverview.js
@@ -393,14 +393,14 @@ var QDR = (function (QDR) {
               }
             else {
               var sumObj = addressObjs[QDRService.utilities.addr_text(identity)+QDRService.utilities.addr_class(identity)]
-              sumObj.inproc = addNull(sumObj.inproc, address.inproc)
-              sumObj.local = addNull(sumObj.local, address.local)
-              sumObj.remote = addNull(sumObj.remote, address.remote)
-              sumObj['in'] = addNull(sumObj['in'], address['in'])
-              sumObj.out = addNull(sumObj.out, address.out)
-              sumObj.thru = addNull(sumObj.thru, address.thru)
-              sumObj.toproc = addNull(sumObj.toproc, address.toproc)
-              sumObj.fromproc = addNull(sumObj.fromproc, address.fromproc)
+              sumObj.inproc = addNull(sumObj.inproc, address.inProcess)
+              sumObj.local = addNull(sumObj.local, address.subscriberCount)
+              sumObj.remote = addNull(sumObj.remote, address.remoteCount)
+              sumObj['in'] = addNull(sumObj['in'], address.deliveriesIngress)
+              sumObj.out = addNull(sumObj.out, address.deliveriesEgress)
+              sumObj.thru = addNull(sumObj.thru, address.deliveriesTransit)
+              sumObj.toproc = addNull(sumObj.toproc, address.deliveriesToContainer)
+              sumObj.fromproc = addNull(sumObj.fromproc, address.deliveriesFromContainer)
             }
           })
         }
@@ -1449,7 +1449,6 @@ return;
         $scope.template = template[0];
       })
     }
-    $scope.template = $scope.templates[0]
     // activated is called each time a tree node is clicked
     // based on which node is clicked, load the correct data grid template and start getting the data
     var onTreeNodeActivated = function (event, data) {
@@ -1469,6 +1468,7 @@ return;
       QDR.redirectWhenConnected($location, "overview")
       return;
     }
+    $scope.template = $scope.templates[0]
 
     /* --------------------------------------------------
      *
@@ -1549,8 +1549,8 @@ return;
     var expandedNodeList = loadExpandedNodeList();
     var firstTime = true;
 
-/*
     var showCharts = function () {
+
     }
     var charts = new Folder("Charts")
     charts.info = {fn: showCharts}
@@ -1558,7 +1558,7 @@ return;
     charts.key = 'Charts'
     charts.extraClasses = "charts"
     topLevelChildren.push(charts)
-*/
+
     // create a routers tree branch
     var routers = new Folder("Routers")
     routers.type = "Routers"
@@ -1733,13 +1733,13 @@ return;
         return;
       }
       $('#overtree').fancytree({
-        activate: onTreeNodeActivated,
-        expand: onTreeNodeExpanded,
-        init: onTreeInitialized,
-        autoCollapse: $scope.largeNetwork,
-        activeVisible: !$scope.largeNetwork,
+        activate:       onTreeNodeActivated,
+        expand:         onTreeNodeExpanded,
+        init:           onTreeInitialized,
+        autoCollapse:   $scope.largeNetwork,
+        activeVisible:! $scope.largeNetwork,
         clickFolderMode: 1,
-        source: topLevelChildren
+        source:         topLevelChildren
       })
     }
 

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/qdrOverviewChartsController.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrOverviewChartsController.js b/console/stand-alone/plugin/js/qdrOverviewChartsController.js
index 73a42fa..335bcb9 100644
--- a/console/stand-alone/plugin/js/qdrOverviewChartsController.js
+++ b/console/stand-alone/plugin/js/qdrOverviewChartsController.js
@@ -21,16 +21,111 @@ under the License.
  */
 var QDR = (function(QDR) {
 
-  QDR.module.controller('QDR.OverviewChartsController', function ($scope, QDRService, $timeout) {
+  QDR.module.controller('QDR.OverviewChartsController', function ($scope, QDRService, QDRChartService, $timeout) {
 
     $scope.overviewCharts = []
+    var updateTimer;
 
+    // called when it is time to update the chart's data
+    var sum = function (request, saveResponse) {
+      var attrs = angular.copy(request.overrideAttrs)
+      var totalAttr = attrs.shift() // remove totals attr
+      var attrEntities = [{entity: request.entity, attrs: attrs}]
+      QDRService.management.topology.fetchAllEntities(attrEntities, function (responses) {
+        var total = 0
+        var response = {attributeNames: [totalAttr, 'name'], results: [[]]}
+        // for each router
+        for (var router in responses) {
+          var record = responses[router][request.entity]
+          var accessor = charts.find( function (chart) { return chart.nodeId === request.nodeId}).accessor
+          // for each attribute-value (ie each address or each link)
+          for (var i=0; i<record.results.length; i++) {
+            total += accessor(record.attributeNames, record.results[i])
+          }
+        }
+        response.results[0][0] = total
+        response.results[0][1] = request.names()[0]
+        saveResponse(request.nodeId, request.entity, response)
+      })
+    }
     var charts = [
-      {}
+
+      {
+        nodeId:     '///Throughput/',
+        entity:     'router.address',
+        name:       'throughput',
+        overrideAttrs: ['throughput', 'deliveriesEgress'],
+        attr:       'throughput',
+        type:       "rate",
+        hideLabel:  true,
+        hideLegend:  true,
+        rateWindow: 5000,   // update data once every 5 seconds
+        visibleDuration: 1, // show data for the last 1 minute
+        forceCreate: true,
+        accessor: function (attributes, results) {
+          return results[attributes.indexOf('deliveriesEgress')]
+        },
+        override: sum  // called to fetch the chart data
+      },
+      {
+        nodeId:       '///Outstanding-Deliveries/',
+        entity:       'router.link',
+        name:         'outstandingDeliveries',
+        overrideAttrs:['outstandingDeliveries', 'undeliveredCount', 'unsettledCount', 'linkType'],
+        attr:         'outstandingDeliveries',
+        hideLabel:  true,
+        hideLegend:  true,
+        visibleDuration: 1, // show data for the last 1 minute
+        forceCreate:  true,
+        accessor: function (attributes, results) {
+          return results[attributes.indexOf('linkType')] === 'endpoint'
+            ? results[attributes.indexOf('unsettledCount')] + results[attributes.indexOf('undeliveredCount')]
+            : 0
+        },
+        now: new Date(),
+        override: sum  // called to fetch the chart data
+      }
     ]
-    // create svg charts
-    //var svgChart = new QDRChartService.pfAreaChart(chart, chart.id(), true)
+    $scope.overviewCharts = charts.map( function (chart) {
+      var c = QDRChartService.registerChart(chart)
+      return new QDRChartService.pfAreaChart(c, c.id(), true)
+    })
+
+
+    // redraw the chart every update period
+    var updateCharts = function () {
+      $scope.overviewCharts.forEach(function (svgChart) {
+        svgChart.tick(svgChart.chart.id()); // on this page we are using the chart.id() as the div id in which to render the chart
+      })
+      var updateRate = localStorage['updateRate'] ?  localStorage['updateRate'] : 1000;
+    }
+
+    var createCharts = function () {
+      // ensure the div for our chart is loaded in the dom
+      var div = angular.element(".chartContainer");
+      if (!div.width()) {
+        setTimeout(createCharts, 100);
+        return;
+      }
+      // create an svg object for each chart
+      $scope.overviewCharts.forEach ( function (c) {
+        // tell c3 to create the svg
+        c.generate()
+      })
+      // redraw the charts once every second
+      updateTimer = setInterval(updateCharts, 1000);
+    }
+    $timeout( function () {
+      createCharts()
+    })
 
+    $scope.$on("$destroy", function(event) {
+      if (updateTimer)
+        clearInterval(updateTimer)
+      $scope.overviewCharts.forEach( function (svg) {
+        QDRChartService.unRegisterChart(svg.chart)
+      })
+    })
   });
   return QDR;
 

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/7f154409/console/stand-alone/plugin/js/qdrTopAddressesController.js
----------------------------------------------------------------------
diff --git a/console/stand-alone/plugin/js/qdrTopAddressesController.js b/console/stand-alone/plugin/js/qdrTopAddressesController.js
new file mode 100644
index 0000000..d5325d7
--- /dev/null
+++ b/console/stand-alone/plugin/js/qdrTopAddressesController.js
@@ -0,0 +1,234 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function(QDR) {
+
+  QDR.module.controller('QDR.TopAddressesController', function ($scope, QDRService, $timeout) {
+
+    var selectRow = function (gridApi) {
+      if (!gridApi.selection)
+        return
+      gridApi.selection.on.rowSelectionChanged($scope,function(row){
+      })
+    }
+    $scope.addressesData = []
+    $scope.topAddressesGrid = {
+      data: 'addressesData',
+      columnDefs: [
+        {
+          field: 'address',
+          displayName: 'address'
+        },
+        {
+          field: 'class',
+          displayName: 'class'
+        },
+/*
+        {
+          field: 'phase',
+          displayName: 'phase',
+          cellClass: 'grid-align-value'
+        },
+        {
+          field: 'inproc',
+          displayName: 'in-proc'
+        },
+        {
+          field: 'local',
+          displayName: 'local',
+          cellClass: 'grid-align-value'
+        },
+        {
+          field: 'remote',
+          displayName: 'remote',
+          cellClass: 'grid-align-value'
+        },
+        */
+        {
+          field: 'in',
+          displayName: 'in',
+          cellClass: 'grid-align-value'
+        },
+        {
+          field: 'out',
+          displayName: 'out',
+          cellClass: 'grid-align-value'
+        }
+      ],
+      enableColumnResize: true,
+      multiSelect: false,
+      enableSelectAll: false,
+      onRegisterApi: selectRow,
+      enableSelectionBatchEvent: false,
+      enableRowHeaderSelection: false,
+      noUnselect: true
+    };
+
+    // get info for all addresses
+    var allAddressInfo = function (address, callback) {
+      var nodes = {}
+      // gets called each node/entity response
+      var gotNode = function (nodeName, entity, response) {
+        if (!nodes[nodeName])
+          nodes[nodeName] = {}
+        nodes[nodeName][entity] = angular.copy(response);
+      }
+      var addr_class = function (addr) {
+        if (!addr) return "-"
+            if (addr[0] == 'M')  return "mobile"
+            if (addr[0] == 'R')  return "router"
+            if (addr[0] == 'A')  return "area"
+            if (addr[0] == 'L')  return "local"
+            if (addr[0] == 'C')  return "link-incoming"
+            if (addr[0] == 'E')  return "link-incoming"
+            if (addr[0] == 'D')  return "link-outgoing"
+            if (addr[0] == 'F')  return "link-outgoing"
+            if (addr[0] == 'T')  return "topo"
+            return "unknown: " + addr[0]
+      }
+      var addr_phase = function (addr) {
+        if (!addr)
+          return "-"
+        if (addr[0] == 'M')
+          return addr[1]
+        return ''
+      }
+      var prettyVal = function (val) {
+        return QDRService.utilities.pretty(val || "-")
+      }
+      var addressFields = []
+      var addressObjs = {}
+      var addNull = function (oldVal, newVal) {
+        if (oldVal != null && newVal != null)
+          return oldVal + newVal
+        if (oldVal != null)
+          return oldVal
+        return newVal
+      }
+      // send the requests for all connection and router info for all routers
+      QDRService.management.topology.fetchAllEntities({entity: "router.address"}, function () {
+        for (var node in nodes) {
+          var response = nodes[node]["router.address"]
+          response.results.forEach( function (result) {
+            var address = QDRService.utilities.flatten(response.attributeNames, result)
+            var uid = address.identity
+            var identity = QDRService.utilities.identity_clean(uid)
+
+            var objname = QDRService.utilities.addr_text(identity)+QDRService.utilities.addr_class(identity)
+            if (!addressObjs[objname]) {
+              addressObjs[objname] = {
+                address: QDRService.utilities.addr_text(identity),
+                'class': QDRService.utilities.addr_class(identity),
+                phase:   addr_phase(identity),
+                inproc:  address.inProcess,
+                local:   address.subscriberCount,
+                remote:  address.remoteCount,
+                'in':    address.deliveriesIngress,
+                out:     address.deliveriesEgress,
+                thru:    address.deliveriesTransit,
+                toproc:  address.deliveriesToContainer,
+                fromproc:address.deliveriesFromContainer,
+                uid:     uid
+              }
+            }
+            else {
+              var sumObj = addressObjs[objname]
+              sumObj.inproc = addNull(sumObj.inproc, address.inProcess)
+              sumObj.local = addNull(sumObj.local, address.subscriberCount)
+              sumObj.remote = addNull(sumObj.remote, address.remoteCount)
+              sumObj['in'] = addNull(sumObj['in'], address.deliveriesIngress)
+              sumObj.out = addNull(sumObj.out, address.deliveriesEgress)
+              sumObj.thru = addNull(sumObj.thru, address.deliveriesTransit)
+              sumObj.toproc = addNull(sumObj.toproc, address.deliveriesToContainer)
+              sumObj.fromproc = addNull(sumObj.fromproc, address.deliveriesFromContainer)
+            }
+          })
+        }
+        for (var obj in addressObjs) {
+          addressObjs[obj].inproc = prettyVal(addressObjs[obj].inproc)
+          addressObjs[obj].local = prettyVal(addressObjs[obj].local)
+          addressObjs[obj].remote = prettyVal(addressObjs[obj].remote)
+          addressObjs[obj]['in'] = prettyVal(addressObjs[obj]['in'])
+          addressObjs[obj].rawout = addressObjs[obj].out
+          addressObjs[obj].out = prettyVal(addressObjs[obj].out)
+          addressObjs[obj].thru = prettyVal(addressObjs[obj].thru)
+          addressObjs[obj].toproc = prettyVal(addressObjs[obj].toproc)
+          addressObjs[obj].fromproc = prettyVal(addressObjs[obj].fromproc)
+          addressFields.push(addressObjs[obj])
+        }
+        if (addressFields.length === 0)
+          return;
+        // update the grid's data
+        addressFields.sort ( function (a,b) {
+          return a.address + a['class'] < b.address + b['class'] ? -1 : a.address + a['class'] > b.address + b['class'] ? 1 : 0}
+        )
+        // callapse all records with same addres+class
+        addressFields[0].title = addressFields[0].address
+        for (var i=1; i<addressFields.length; ++i) {
+          // if this address is the same as the previous address, add a class to the display titles
+          if (addressFields[i].address === addressFields[i-1].address) {
+            addressFields[i-1].title = addressFields[i-1].address + " (" + addressFields[i-1]['class'] + ")"
+            addressFields[i].title = addressFields[i].address + " (" + addressFields[i]['class'] + ")"
+          } else
+            addressFields[i].title = addressFields[i].address
+        }
+        addressFields = addressFields.filter( function (address) {
+          return address.rawout > 0 || address.rawin > 0
+        })
+        addressFields.sort ( function (a,b) {
+          return a.rawout < b.rawout ? -1 : a.rawout > b.rawout ? 1 : 0}
+        )
+        // take top 5 records
+        addressFields.splice(5)
+
+        $scope.addressesData = addressFields
+        callback(null)
+      }, gotNode)
+    }
+    var timer;
+    var updateGrid = function () {
+      $timeout( function () {
+        allAddressInfo(null, function () {console.log('done')})
+        expandGridToContent($scope.addressesData.length)
+      })
+    }
+    timer = setInterval(updateGrid, 5000)
+    updateGrid()
+
+    var expandGridToContent = function (rows) {
+      var height = (rows+1) * 30 + 40 // header is 40px
+      var gridDetails = $('#overview-controller .grid')
+      gridDetails.css('height', height + "px")
+    }
+
+    $scope.anyAddresses = function () {
+      return $scope.addressesData.length > 0
+    }
+
+    $scope.$on("$destroy", function( event ) {
+      if (timer)
+        clearInterval(timer)
+    });
+
+  });
+  return QDR;
+
+} (QDR || {}));


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org