github.com/ghodss/etcd@v0.3.1-0.20140417172404-cc329bfa55cb/mod/dashboard/app/scripts/controllers/stats.js (about) 1 'use strict'; 2 3 4 angular.module('etcdControlPanel') 5 .controller('StatsCtrl', function ($scope, $rootScope, $interval, EtcdV2, statsVega, vg) { 6 $scope.graphContainer = '#latency'; 7 $scope.graphVisibility = 'etcd-graph-show'; 8 $scope.tableVisibility = 'etcd-table-hide'; 9 10 //make requests 11 function readStats() { 12 EtcdV2.getStat('leader').get().success(function(data) { 13 $scope.leaderStats = data; 14 $scope.leaderName = data.leader; 15 $scope.peers = []; 16 //hardcode leader stats 17 $scope.peers.push({ 18 latency: { 19 average: 0, 20 current: 0, 21 minimum: 0, 22 maximum: 0, 23 standardDeviation: 0 24 }, 25 name: data.leader 26 }); 27 $.each(data.followers, function(index, value) { 28 value.name = index; 29 $scope.peers.push(value); 30 }); 31 //sort array so peers don't jump when output 32 $scope.peers.sort(function(a, b){ 33 if(a.name < b.name) { 34 return -1; 35 } 36 if(a.name > b.name) { 37 return 1; 38 } 39 return 0; 40 }); 41 drawGraph(); 42 }); 43 } 44 45 function drawGraph () { 46 //hardcoded padding from chart json 47 var vertPadding = 30; 48 var horzPadding = 15; 49 //fetch width and height of graph area 50 var width = $($scope.graphContainer).width() - horzPadding; 51 var height = $($scope.graphContainer).height() - vertPadding; 52 53 // parse a spec and create a visualization view 54 function parse(spec) { 55 vg.parse.spec(spec, function(chart) { 56 chart({ 57 el: $scope.graphContainer, 58 data: { 59 'stats': $scope.peers 60 } 61 }).width(width).height(height).update(); 62 }); 63 } 64 parse(statsVega); 65 } 66 67 $scope.showTable = function() { 68 $scope.tableVisibility = 'etcd-table-reveal'; 69 }; 70 71 $scope.showGraph = function() { 72 $scope.tableVisibility = 'etcd-table-hide'; 73 }; 74 75 $scope.getHeight = function() { 76 return $(window).height(); 77 }; 78 $scope.getWidth = function() { 79 return $(window).width(); 80 }; 81 //$scope.$watch($scope.getHeight, function() { 82 ////$('.etcd-container.etcd-stats .etcd-body').css('height', $scope.getHeight()-5); 83 //readStats(); 84 //}); 85 $scope.$watch($scope.getWidth, function() { 86 readStats(); 87 }); 88 window.onresize = function(){ 89 $scope.$apply(); 90 }; 91 92 $scope.pollPromise = null; 93 94 $scope.startPolling = function() { 95 // Update the graphs live 96 if ($scope.pollPromise) { 97 return; 98 } 99 $scope.pollPromise = $interval(function() { 100 readStats(); 101 }, 500); 102 }; 103 104 $scope.stopPolling = function() { 105 $interval.cancel($scope.pollPromise); 106 $scope.pollPromise = null; 107 }; 108 109 // Stop polling when navigating away from a view with this controller. 110 $rootScope.$on('$routeChangeStart', function () { 111 $scope.stopPolling(); 112 }); 113 114 $scope.startPolling(); 115 116 }) 117 118 119 /* statsVega returns the vega configuration for the stats dashboard */ 120 .factory('statsVega', function () { 121 return { 122 'padding': {'top': 10, 'left': 5, 'bottom': 40, 'right': 10}, 123 'data': [ 124 { 125 'name': 'stats' 126 }, 127 { 128 'name': 'thresholds', 129 'values': [50, 100] 130 } 131 ], 132 'scales': [ 133 { 134 'name': 'y', 135 'type': 'ordinal', 136 'range': 'height', 137 'domain': {'data': 'stats', 'field': 'index'} 138 }, 139 { 140 'name': 'x', 141 'range': 'width', 142 'domainMin': 0, 143 'domainMax': 100, 144 'nice': true, 145 'zero': true, 146 'domain': {'data': 'stats', 'field': 'data.latency.current'} 147 }, 148 { 149 'name': 'color', 150 'type': 'linear', 151 'domain': [10, 50, 100, 1000000000], 152 'range': ['#00DB24', '#FFC000', '#c40022', '#c40022'] 153 } 154 ], 155 'axes': [ 156 { 157 'type': 'x', 158 'scale': 'x', 159 'ticks': 6, 160 'name': 'Latency (ms)' 161 }, 162 { 163 'type': 'y', 164 'scale': 'y', 165 'properties': { 166 'ticks': { 167 'stroke': {'value': 'transparent'} 168 }, 169 'majorTicks': { 170 'stroke': {'value': 'transparent'} 171 }, 172 'labels': { 173 'fill': {'value': 'transparent'} 174 }, 175 'axis': { 176 'stroke': {'value': '#333'}, 177 'strokeWidth': {'value': 1} 178 } 179 } 180 } 181 ], 182 'marks': [ 183 { 184 'type': 'rect', 185 'from': {'data': 'stats'}, 186 'properties': { 187 'enter': { 188 'x': {'scale': 'x', 'value': 0}, 189 'x2': {'scale': 'x', 'field': 'data.latency.current'}, 190 'y': {'scale': 'y', 'field': 'index', 'offset': -1}, 191 'height': {'value': 3}, 192 'fill': {'scale':'color', 'field':'data.latency.current'} 193 } 194 } 195 }, 196 { 197 'type': 'symbol', 198 'from': {'data': 'stats'}, 199 'properties': { 200 'enter': { 201 'x': {'scale': 'x', 'field': 'data.latency.current'}, 202 'y': {'scale': 'y', 'field': 'index'}, 203 'size': {'value': 50}, 204 'fill': {'value': '#000'} 205 } 206 } 207 } 208 ] 209 }; 210 });