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