You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2014/01/22 22:42:00 UTC

[7/8] git commit: Added a Top abstraction to the webui.

Added a Top abstraction to the webui.

This allows the webui to asynchronously update resource consumption
information without every Slave controller having to implement this.

Review: https://reviews.apache.org/r/13606


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

Branch: refs/heads/master
Commit: ed3f0438d56b007999769152c820c3585cfa540d
Parents: 8b095fe
Author: Benjamin Mahler <bm...@twitter.com>
Authored: Thu Jul 25 14:50:41 2013 -0700
Committer: Benjamin Mahler <bm...@twitter.com>
Committed: Wed Jan 22 13:03:11 2014 -0800

----------------------------------------------------------------------
 src/webui/master/static/js/controllers.js    | 279 ++++++++++------------
 src/webui/master/static/js/services.js       | 186 +++++++++++++++
 src/webui/master/static/slave.html           |  18 +-
 src/webui/master/static/slave_executor.html  |   6 +-
 src/webui/master/static/slave_framework.html |   8 +-
 5 files changed, 332 insertions(+), 165 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ed3f0438/src/webui/master/static/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/controllers.js b/src/webui/master/static/js/controllers.js
index 01fe64c..afb24fb 100644
--- a/src/webui/master/static/js/controllers.js
+++ b/src/webui/master/static/js/controllers.js
@@ -381,7 +381,9 @@
   mesosApp.controller('SlavesCtrl', function() {});
 
 
-  mesosApp.controller('SlaveCtrl', function($dialog, $scope, $routeParams, $http, $q) {
+  mesosApp.controller('SlaveCtrl', [
+      '$dialog', '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
+      function($dialog, $scope, $routeParams, $http, $q, $timeout, $top) {
     $scope.slave_id = $routeParams.slave_id;
 
     var update = function() {
@@ -408,56 +410,55 @@
         }
       };
 
-      var usageRequest = $http.jsonp(
-          'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
-
-      var stateRequest = $http.jsonp(
-          'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
-
-      $q.all([usageRequest, stateRequest]).then(function (responses) {
-        $scope.monitor = responses[0].data;
-        $scope.state = responses[1].data;
-
-        $scope.slave = {};
-        $scope.slave.frameworks = {};
-        $scope.slave.completed_frameworks = {};
-
-        $scope.slave.staging_tasks = 0;
-        $scope.slave.starting_tasks = 0;
-        $scope.slave.running_tasks = 0;
+      // Set up polling for the monitor if this is the first update.
+      if (!$top.started()) {
+        $top.start(host, $scope);
+      }
 
-        // Computes framework stats by setting new attributes on the 'framework'
-        // object.
-        function computeFrameworkStats(framework) {
-          framework.num_tasks = 0;
-          framework.cpus = 0;
-          framework.mem = 0;
+      $http.jsonp('http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK')
+        .success(function (response) {
+          $scope.state = response;
+
+          $scope.slave = {};
+          $scope.slave.frameworks = {};
+          $scope.slave.completed_frameworks = {};
+
+          $scope.slave.staging_tasks = 0;
+          $scope.slave.starting_tasks = 0;
+          $scope.slave.running_tasks = 0;
+
+          // Computes framework stats by setting new attributes on the 'framework'
+          // object.
+          function computeFrameworkStats(framework) {
+            framework.num_tasks = 0;
+            framework.cpus = 0;
+            framework.mem = 0;
+
+            _.each(framework.executors, function(executor) {
+              framework.num_tasks += _.size(executor.tasks);
+              framework.cpus += executor.resources.cpus;
+              framework.mem += executor.resources.mem;
+            });
+          }
 
-          _.each(framework.executors, function(executor) {
-            framework.num_tasks += _.size(executor.tasks);
-            framework.cpus += executor.resources.cpus;
-            framework.mem += executor.resources.mem;
+          // Compute framework stats and update slave's mappings of those
+          // frameworks.
+          _.each($scope.state.frameworks, function(framework) {
+            $scope.slave.frameworks[framework.id] = framework;
+            computeFrameworkStats(framework);
           });
-        }
 
-        // Compute framework stats and update slave's mappings of those
-        // frameworks.
-        _.each($scope.state.frameworks, function(framework) {
-          $scope.slave.frameworks[framework.id] = framework;
-          computeFrameworkStats(framework);
-        });
+          _.each($scope.state.completed_frameworks, function(framework) {
+            $scope.slave.completed_frameworks[framework.id] = framework;
+            computeFrameworkStats(framework);
+          });
 
-        _.each($scope.state.completed_frameworks, function(framework) {
-          $scope.slave.completed_frameworks[framework.id] = framework;
-          computeFrameworkStats(framework);
+          $('#slave').show();
+        })
+        .error(function(reason) {
+          $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
+          $('#alert').show();
         });
-
-        $('#slave').show();
-      },
-      function (reason) {
-        $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
-        $('#alert').show();
-      });
     };
 
     if ($scope.state) {
@@ -466,10 +467,12 @@
 
     var removeListener = $scope.$on('state_updated', update);
     $scope.$on('$routeChangeStart', removeListener);
-  });
+  }]);
 
 
-  mesosApp.controller('SlaveFrameworkCtrl', function($scope, $routeParams, $http, $q) {
+  mesosApp.controller('SlaveFrameworkCtrl', [
+      '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
+      function($scope, $routeParams, $http, $q, $timeout, $top) {
     $scope.slave_id = $routeParams.slave_id;
     $scope.framework_id = $routeParams.framework_id;
 
@@ -485,72 +488,49 @@
       var id = pid.substring(0, pid.indexOf('@'));
       var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
 
-      var usageRequest = $http.jsonp(
-          'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
-
-      var stateRequest = $http.jsonp(
-          'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
-
-      $q.all([usageRequest, stateRequest]).then(function (responses) {
-        var monitor = responses[0].data;
-        $scope.state = responses[1].data;
+      // Set up polling for the monitor if this is the first update.
+      if (!$top.started()) {
+        $top.start(host, $scope);
+      }
 
-        $scope.slave = {};
+      $http.jsonp('http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK')
+        .success(function (response) {
+          $scope.state = response;
 
-        function matchFramework(framework) {
-          return $scope.framework_id === framework.id;
-        }
+          $scope.slave = {};
 
-        // Find the framework; it's either active or completed.
-        $scope.framework =
-            _.find($scope.state.frameworks, matchFramework) ||
-            _.find($scope.state.completed_frameworks, matchFramework);
-
-        if (!$scope.framework) {
-          $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
-          $('#alert').show();
-          return;
-        }
+          function matchFramework(framework) {
+            return $scope.framework_id === framework.id;
+          }
 
-        // Compute the framework stats.
-        $scope.framework.num_tasks = 0;
-        $scope.framework.cpus = 0;
-        $scope.framework.mem = 0;
+          // Find the framework; it's either active or completed.
+          $scope.framework =
+              _.find($scope.state.frameworks, matchFramework) ||
+              _.find($scope.state.completed_frameworks, matchFramework);
 
-        _.each($scope.framework.executors, function(executor) {
-          $scope.framework.num_tasks += _.size(executor.tasks);
-          $scope.framework.cpus += executor.resources.cpus;
-          $scope.framework.mem += executor.resources.mem;
-        });
+          if (!$scope.framework) {
+            $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+            $('#alert').show();
+            return;
+          }
 
-        // Index the monitoring data.
-        $scope.monitor = {};
+          // Compute the framework stats.
+          $scope.framework.num_tasks = 0;
+          $scope.framework.cpus = 0;
+          $scope.framework.mem = 0;
 
-        $scope.framework.resource_usage = {};
-        $scope.framework.resource_usage["cpu_time"] = 0.0;
-        $scope.framework.resource_usage["cpu_usage"] = 0.0;
-        $scope.framework.resource_usage["memory_rss"] = 0.0;
+          _.each($scope.framework.executors, function(executor) {
+            $scope.framework.num_tasks += _.size(executor.tasks);
+            $scope.framework.cpus += executor.resources.cpus;
+            $scope.framework.mem += executor.resources.mem;
+          });
 
-        _.each(monitor, function(executor) {
-          if (!$scope.monitor[executor.framework_id]) {
-            $scope.monitor[executor.framework_id] = {};
-          }
-          $scope.monitor[executor.framework_id][executor.executor_id] = executor;
-
-          $scope.framework.resource_usage["cpu_time"] +=
-            executor.resource_usage.cpu_time;
-          $scope.framework.resource_usage["cpu_usage"] +=
-            executor.resource_usage.cpu_usage;
-          $scope.framework.resource_usage["memory_rss"] +=
-            executor.resource_usage.memory_rss;
+          $('#slave').show();
+        })
+        .error(function (reason) {
+          $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
+          $('#alert').show();
         });
-
-        $('#slave').show();
-      },
-      function (reason) {
-        $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
-        $('#alert').show();
-      });
     };
 
     if ($scope.state) {
@@ -559,10 +539,12 @@
 
     var removeListener = $scope.$on('state_updated', update);
     $scope.$on('$routeChangeStart', removeListener);
-  });
+  }]);
 
 
-  mesosApp.controller('SlaveExecutorCtrl', function($scope, $routeParams, $http, $q) {
+  mesosApp.controller('SlaveExecutorCtrl', [
+      '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
+      function($scope, $routeParams, $http, $q, $timeout, $top) {
     $scope.slave_id = $routeParams.slave_id;
     $scope.framework_id = $routeParams.framework_id;
     $scope.executor_id = $routeParams.executor_id;
@@ -579,64 +561,53 @@
       var id = pid.substring(0, pid.indexOf('@'));
       var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
 
-      var usageRequest = $http.jsonp(
-          'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
+      // Set up polling for the monitor if this is the first update.
+      if (!$top.started()) {
+        $top.start(host, $scope);
+      }
 
-      var stateRequest = $http.jsonp(
-          'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
+      $http.jsonp('http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK')
+        .success(function (response) {
+          $scope.state = response;
 
-      $q.all([usageRequest, stateRequest]).then(function (responses) {
-        var monitor = responses[0].data;
-        $scope.state = responses[1].data;
+          $scope.slave = {};
 
-        $scope.slave = {};
+          function matchFramework(framework) {
+            return $scope.framework_id === framework.id;
+          }
 
-        function matchFramework(framework) {
-          return $scope.framework_id === framework.id;
-        }
+          // Find the framework; it's either active or completed.
+          $scope.framework =
+            _.find($scope.state.frameworks, matchFramework) ||
+            _.find($scope.state.completed_frameworks, matchFramework);
 
-        // Find the framework; it's either active or completed.
-        $scope.framework =
-          _.find($scope.state.frameworks, matchFramework) ||
-          _.find($scope.state.completed_frameworks, matchFramework);
+          if (!$scope.framework) {
+            $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+            $('#alert').show();
+            return;
+          }
 
-        if (!$scope.framework) {
-          $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
-          $('#alert').show();
-          return;
-        }
+          function matchExecutor(executor) {
+            return $scope.executor_id === executor.id;
+          }
 
-        function matchExecutor(executor) {
-          return $scope.executor_id === executor.id;
-        }
+          // Look for the executor; it's either active or completed.
+          $scope.executor =
+            _.find($scope.framework.executors, matchExecutor) ||
+            _.find($scope.framework.completed_executors, matchExecutor);
 
-        // Look for the executor; it's either active or completed.
-        $scope.executor =
-          _.find($scope.framework.executors, matchExecutor) ||
-          _.find($scope.framework.completed_executors, matchExecutor);
+          if (!$scope.executor) {
+            $scope.alert_message = 'No executor found with ID: ' + $routeParams.executor_id;
+            $('#alert').show();
+            return;
+          }
 
-        if (!$scope.executor) {
-          $scope.alert_message = 'No executor found with ID: ' + $routeParams.executor_id;
+          $('#slave').show();
+        })
+        .error(function (reason) {
+          $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
           $('#alert').show();
-          return;
-        }
-
-        // Index the monitoring data.
-        $scope.monitor = {};
-
-        _.each(monitor, function(executor) {
-          if (!$scope.monitor[executor.framework_id]) {
-            $scope.monitor[executor.framework_id] = {};
-          }
-          $scope.monitor[executor.framework_id][executor.executor_id] = executor;
         });
-
-        $('#slave').show();
-      },
-      function (reason) {
-        $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
-        $('#alert').show();
-      });
     };
 
     if ($scope.state) {
@@ -645,7 +616,7 @@
 
     var removeListener = $scope.$on('state_updated', update);
     $scope.$on('$routeChangeStart', removeListener);
-  });
+  }]);
 
 
   // Reroutes a request like

http://git-wip-us.apache.org/repos/asf/mesos/blob/ed3f0438/src/webui/master/static/js/services.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/services.js b/src/webui/master/static/js/services.js
index 122519a..8403aad 100644
--- a/src/webui/master/static/js/services.js
+++ b/src/webui/master/static/js/services.js
@@ -105,4 +105,190 @@
         }
       };
     }]);
+
+  function Statistics() {
+    this.cpus_user_time_secs = 0.0;
+    this.cpus_user_usage = 0.0;
+    this.cpus_system_time_secs = 0.0;
+    this.cpus_system_usage = 0.0;
+    this.cpus_limit = 0.0;
+    this.cpus_total_usage = 0.0;
+    this.mem_rss_bytes = 0.0;
+    this.mem_limit_bytes = 0.0;
+  }
+
+  Statistics.prototype.add = function(statistics) {
+    this.cpus_user_time_secs += statistics.cpus_user_time_secs;
+    this.cpus_system_time_secs += statistics.cpus_system_time_secs;
+    this.cpus_total_usage += statistics.cpus_total_usage;
+    this.cpus_limit += statistics.cpus_limit;
+    this.mem_rss_bytes += statistics.mem_rss_bytes;
+    this.mem_limit_bytes += statistics.mem_limit_bytes;
+
+    // Set instead of add the timestamp since this is an instantaneous view of
+    // CPU usage since the last poll.
+    this.timestamp = statistics.timestamp;
+  };
+
+  Statistics.prototype.diffUsage = function(statistics) {
+    this.cpus_user_usage =
+      (this.cpus_user_time_secs - statistics.cpus_user_time_secs) /
+      (this.timestamp - statistics.timestamp);
+    this.cpus_system_usage =
+      (this.cpus_system_time_secs - statistics.cpus_system_time_secs) /
+      (this.timestamp - statistics.timestamp);
+    this.cpus_total_usage = this.cpus_user_usage + this.cpus_system_usage;
+  };
+
+  Statistics.parseJSON = function(json) {
+    var statistics = new Statistics();
+    statistics.add(json);
+    return statistics;
+  };
+
+  // Top is an abstraction for polling a slave's monitoring endpoint to
+  // periodically update the monitoring data. It also computes CPU usage.
+  // This places the following data in scope.monitor:
+  //
+  //   $scope.monitor = {
+  //     "statistics": <stats>,
+  //     "frameworks": {
+  //       <framework_id>: {
+  //         "statistics": <stats>,
+  //         "executors": {
+  //           <executor_id>: {
+  //             "executor_id": <executor_id>,
+  //             "framework_id": <framework_id>,
+  //             "executor_name: <executor_name>,
+  //             "source": <source>,
+  //             "statistics": <stats>,
+  //           }
+  //         }
+  //       }
+  //     }
+  //    }
+  //
+  // To obtain slave statistics:
+  //   $scope.monitor.statistics
+  //
+  // To obtain a framework's statistics:
+  //   $scope.monitor.frameworks[<framework_id>].statistics
+  //
+  // To obtain an executor's statistics:
+  //   $scope.monitor.frameworks[<framework_id>].executors[<executor_id>].statistics
+  //
+  // In the above,  <stats> is the following object:
+  //
+  //   {
+  //     cpus_user_time_secs: value,
+  //     cpus_user_usage: value, // Once computed.
+  //     cpus_system_time_secs: value,
+  //     cpus_system_usage: value, // Once computed.
+  //     mem_limit_bytes: value,
+  //     mem_rss_bytes: value,
+  //   }
+  //
+  // TODO(bmahler): The complexity of the monitor object is mostly in place
+  // until we have path-params on the monitoring endpoint to request
+  // statistics for the slave, or for a specific framework / executor.
+  //
+  // Arguments:
+  //   http: $http service from Angular.
+  //   timeout: $timeout service from Angular.
+  function Top($http, $timeout) {
+    this.http = $http;
+    this.timeout = $timeout;
+  }
+
+  Top.prototype.poll = function() {
+    this.http.jsonp(this.endpoint)
+
+      // Success! Parse the response.
+      .success(angular.bind(this, this.parseResponse))
+
+      // Do not continue polling on error.
+      .error(angular.noop);
+  };
+
+  Top.prototype.parseResponse = function(response) {
+    var that = this;
+    var monitor = {
+      frameworks: {},
+      statistics: new Statistics()
+    };
+
+    response.forEach(function(executor) {
+      var executor_id = executor.executor_id;
+      var framework_id = executor.framework_id;
+      var current = executor.statistics =
+        Statistics.parseJSON(executor.statistics);
+
+      current.cpus_user_usage = 0.0;
+      current.cpus_system_usage = 0.0;
+
+      // Compute CPU usage if possible.
+      if (that.scope.monitor &&
+          that.scope.monitor.frameworks[framework_id] &&
+          that.scope.monitor.frameworks[framework_id].executors[executor_id]) {
+        var previous = that.scope.monitor.frameworks[framework_id].executors[executor_id].statistics;
+        current.diffUsage(previous);
+      }
+
+      // Index the data.
+      if (!monitor.frameworks[executor.framework_id]) {
+        monitor.frameworks[executor.framework_id] = {
+          executors: {},
+          statistics: new Statistics()
+        };
+      }
+
+      // Aggregate these statistics into the slave and framework statistics.
+      monitor.statistics.add(current);
+      monitor.frameworks[executor.framework_id].statistics.add(current);
+      monitor.frameworks[executor.framework_id].executors[executor.executor_id] = {
+        statistics: current
+      };
+    });
+
+    if (this.scope.monitor) {
+      // Continue polling.
+      this.polling = this.timeout(angular.bind(this, this.poll), 3000);
+    } else {
+      // Try to compute initial CPU usage more quickly than 3 seconds.
+      this.polling = this.timeout(angular.bind(this, this.poll), 500);
+    }
+
+    // Update the monitoring data.
+    this.scope.monitor = monitor;
+  };
+
+  // Arguments:
+  //   host: host of slave.
+  //   scope: $scope service from Angular.
+  Top.prototype.start = function(host, scope) {
+    if (this.started()) {
+      // TODO(bmahler): Consider logging a warning here.
+      return;
+    }
+
+    this.endpoint = 'http://' + host + '/monitor/statistics.json?jsonp=JSON_CALLBACK';
+    this.scope = scope;
+
+    // Initial poll is immediate.
+    this.polling = this.timeout(angular.bind(this, this.poll), 0);
+
+    // Stop when we leave the page.
+    scope.$on('$routeChangeStart', angular.bind(this, this.stop));
+  };
+
+  Top.prototype.started = function() {
+    return this.polling != null;
+  };
+
+  Top.prototype.stop = function() {
+    this.timeout.cancel(this.polling);
+    this.polling = null;
+  };
+
+  mesosServices.service('top', ['$http', '$timeout', Top]);
 })();

http://git-wip-us.apache.org/repos/asf/mesos/blob/ed3f0438/src/webui/master/static/slave.html
----------------------------------------------------------------------
diff --git a/src/webui/master/static/slave.html b/src/webui/master/static/slave.html
index cf927dc..09bfcf2 100644
--- a/src/webui/master/static/slave.html
+++ b/src/webui/master/static/slave.html
@@ -76,19 +76,29 @@
 
       <h4>Resources</h4>
       <table class="table table-condensed">
+        <thead>
+          <tr>
+            <td></td>
+            <td class="text-right">Used</td>
+            <td class="text-right">Allocated</td>
+          </tr>
+        </thead>
         <tbody>
           <tr>
             <td>CPUs</td>
+            <td class="text-right">{{monitor.statistics.cpus_total_usage | number}}</td>
             <td class="text-right">{{state.resources.cpus | number}}</td>
           </tr>
           <tr>
             <td>Memory</td>
+            <td class="text-right">{{monitor.statistics.mem_rss_bytes | dataSize}}</td>
             <td class="text-right">
               {{state.resources.mem * (1024 * 1024) | dataSize}}
             </td>
           </tr>
           <tr>
             <td>Disk</td>
+            <td class="text-right">{{0 | dataSize}}</td>
             <td class="text-right">
               {{state.resources.disk * (1024 * 1024) | dataSize}}
             </td>
@@ -107,8 +117,8 @@
           <th data-key="user">User</th>
           <th data-key="name">Name</th>
           <th data-key="num_tasks">Active Tasks</th>
-          <th data-key="cpus">CPUs</th>
-          <th data-key="Mem">Mem</th>
+          <th data-key="cpus">CPUs (Used / Allocated)</th>
+          <th data-key="Mem">Mem (Used / Allocated)</th>
         </tr>
       </thead>
       <tbody>
@@ -127,8 +137,8 @@
           <td>{{framework.user}}</td>
           <td>{{framework.name}}</td>
           <td>{{framework.num_tasks | number}}</td>
-          <td>{{framework.cpus | number}}</td>
-          <td>{{framework.mem * (1024 * 1024) | dataSize}}</td>
+          <td>{{monitor.frameworks[framework.id].statistics.cpus_user_usage + monitor.frameworks[framework.id].statistics.cpus_system_usage | number}} / {{framework.cpus | number}}</td>
+          <td>{{monitor.frameworks[framework.id].statistics.mem_rss_bytes | dataSize}} / {{framework.mem * (1024 * 1024) | dataSize}}</td>
         </tr>
       </tbody>
     </table>

http://git-wip-us.apache.org/repos/asf/mesos/blob/ed3f0438/src/webui/master/static/slave_executor.html
----------------------------------------------------------------------
diff --git a/src/webui/master/static/slave_executor.html b/src/webui/master/static/slave_executor.html
index 5c349c1..7c66405 100644
--- a/src/webui/master/static/slave_executor.html
+++ b/src/webui/master/static/slave_executor.html
@@ -64,14 +64,14 @@
           <tr>
             <td>CPUs</td>
             <td class="text-right">
-              {{monitor[framework.id][executor.id].resource_usage.cpu_usage | number}}
+              {{monitor.frameworks[framework.id].executors[executor.id].statistics.cpus_total_usage | number}}
             </td>
             <td class="text-right">{{executor.resources.cpus | number}}</td>
           </tr>
           <tr>
             <td>Mem</td>
             <td class="text-right">
-              {{monitor[framework.id][executor.id].resource_usage.memory_rss | dataSize}}
+              {{monitor.frameworks[framework.id].executors[executor.id].statistics.mem_rss_bytes | dataSize}}
             </td>
             <td class="text-right">
               {{executor.resources.mem * (1024 * 1024) | dataSize}}
@@ -79,7 +79,7 @@
           </tr>
           <tr>
             <td>Disk</td>
-            <td class="text-right">-</td>
+            <td class="text-right">{{0 | dataSize}}</td>
             <td class="text-right">
               {{(executor.resources.disk || 0) * (1024 * 1024) | dataSize}}
             </td>

http://git-wip-us.apache.org/repos/asf/mesos/blob/ed3f0438/src/webui/master/static/slave_framework.html
----------------------------------------------------------------------
diff --git a/src/webui/master/static/slave_framework.html b/src/webui/master/static/slave_framework.html
index af52cf9..90eff2f 100644
--- a/src/webui/master/static/slave_framework.html
+++ b/src/webui/master/static/slave_framework.html
@@ -43,14 +43,14 @@
           <tr>
             <td>CPUs</td>
             <td class="text-right">
-              {{framework.resource_usage.cpu_usage | number}}
+              {{monitor.frameworks[framework.id].statistics.cpus_total_usage | number}}
             </td>
             <td class="text-right">{{framework.cpus | number}}</td>
           </tr>
           <tr>
             <td>Memory</td>
             <td class="text-right">
-              {{framework.resource_usage.memory_rss | dataSize}}
+              {{monitor.frameworks[framework.id].statistics.mem_rss_bytes | dataSize}}
             </td>
             <td class="text-right">
               {{framework.mem * (1024 * 1024) | dataSize}}
@@ -94,9 +94,9 @@
           <td>{{executor.source}}</td>
           <td>{{executor.tasks.length | number}}</td>
           <td>{{executor.queued_tasks.length | number}}</td>
-          <td>{{monitor[framework_id][executor.id].resource_usage.cpu_usage | number}} /
+          <td>{{monitor.frameworks[framework.id].executors[executor.id].statistics.cpus_user_usage + monitor.frameworks[framework.id].executors[executor.id].statistics.cpus_system_usage | number}} /
               {{executor.resources.cpus | number}}</td>
-          <td>{{monitor[framework_id][executor.id].resource_usage.memory_rss | dataSize}} /
+          <td>{{monitor.frameworks[framework.id].executors[executor.id].statistics.mem_rss_bytes | dataSize}} /
               {{executor.resources.mem * (1024 * 1024) | dataSize}}</td>
           <td>
             <a href="{{'#/slaves/' + slave_id + '/browse?path=' +