ozone.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. (function() {
  19. "use strict";
  20. var isIgnoredJmxKeys = function(key) {
  21. return key == 'name' || key == 'modelerType' || key == "$$hashKey" ||
  22. key.match(/tag.*/);
  23. };
  24. angular.module('ozone', ['nvd3', 'ngRoute']);
  25. angular.module('ozone').config(function($routeProvider) {
  26. $routeProvider
  27. .when("/", {
  28. templateUrl: "main.html"
  29. })
  30. .when("/metrics/rpc", {
  31. template: "<rpc-metrics></rpc-metrics>"
  32. })
  33. .when("/config", {
  34. template: "<config></config>"
  35. })
  36. });
  37. angular.module('ozone').component('overview', {
  38. templateUrl: 'static/templates/overview.html',
  39. transclude: true,
  40. controller: function($http) {
  41. var ctrl = this;
  42. $http.get("jmx?qry=Hadoop:service=*,name=*,component=ServerRuntime")
  43. .then(function(result) {
  44. ctrl.jmx = result.data.beans[0]
  45. })
  46. }
  47. });
  48. angular.module('ozone').component('jvmParameters', {
  49. templateUrl: 'static/templates/jvm.html',
  50. controller: function($http) {
  51. var ctrl = this;
  52. $http.get("jmx?qry=java.lang:type=Runtime")
  53. .then(function(result) {
  54. ctrl.jmx = result.data.beans[0];
  55. //convert array to a map
  56. var systemProperties = {};
  57. for (var idx in ctrl.jmx.SystemProperties) {
  58. var item = ctrl.jmx.SystemProperties[idx];
  59. systemProperties[item.key.replace(/\./g, "_")] = item.value;
  60. }
  61. ctrl.jmx.SystemProperties = systemProperties;
  62. })
  63. }
  64. });
  65. angular.module('ozone').component('rpcMetrics', {
  66. template: '<h1>Rpc metrics</h1><tabs>' +
  67. '<pane ng-repeat="metric in $ctrl.metrics" ' +
  68. 'title="{{metric[\'tag.serverName\']}} ({{metric[\'tag.port\']}})">' +
  69. '<rpc-metric jmxdata="metric"></rpc-metric></pane>' +
  70. '</tabs>',
  71. controller: function($http) {
  72. var ctrl = this;
  73. $http.get("jmx?qry=Hadoop:service=*,name=RpcActivityForPort*")
  74. .then(function(result) {
  75. ctrl.metrics = result.data.beans;
  76. })
  77. }
  78. });
  79. angular.module('ozone').component('rpcMetric', {
  80. bindings: {
  81. jmxdata: '<'
  82. },
  83. templateUrl: 'static/templates/rpc-metrics.html',
  84. controller: function() {
  85. var ctrl = this;
  86. ctrl.percentileGraphOptions = {
  87. chart: {
  88. type: 'discreteBarChart',
  89. height: 450,
  90. margin: {
  91. top: 20,
  92. right: 20,
  93. bottom: 50,
  94. left: 55
  95. },
  96. x: function(d) {
  97. return d.label;
  98. },
  99. y: function(d) {
  100. return d.value;
  101. },
  102. showValues: true,
  103. valueFormat: function(d) {
  104. return d3.format(',.1f')(d);
  105. },
  106. duration: 500,
  107. xAxis: {
  108. axisLabel: 'Percentage'
  109. },
  110. yAxis: {
  111. axisLabel: 'Latency (ms)',
  112. axisLabelDistance: -10
  113. }
  114. }
  115. };
  116. ctrl.$onChanges = function(data) {
  117. var groupedMetrics = {}
  118. var createPercentageMetrics = function(metricName, window) {
  119. groupedMetrics.percentiles = groupedMetrics['percentiles'] || {}
  120. groupedMetrics.percentiles[window] = groupedMetrics.percentiles[window] || {};
  121. groupedMetrics.percentiles[window][metricName] = groupedMetrics.percentiles[window][metricName] || {
  122. graphdata: [{
  123. key: window,
  124. values: []
  125. }],
  126. numOps: 0
  127. };
  128. };
  129. var metrics = ctrl.jmxdata;
  130. for (var key in metrics) {
  131. var percentile = key.match(/(.*Time)(\d+s)(\d+th)PercentileLatency/);
  132. var percentileNumOps = key.match(/(.*Time)(\d+s)NumOps/);
  133. var successFailures = key.match(/(.*)(Success|Failures)/);
  134. var numAverages = key.match(/(.*Time)(NumOps|AvgTime)/);
  135. if (percentile) {
  136. var metricName = percentile[1];
  137. var window = percentile[2];
  138. var percentage = percentile[3]
  139. createPercentageMetrics(metricName, window);
  140. groupedMetrics.percentiles[window][metricName].graphdata[0]
  141. .values.push({
  142. label: percentage,
  143. value: metrics[key]
  144. })
  145. } else if (successFailures) {
  146. var metricName = successFailures[1];
  147. groupedMetrics.successfailures = groupedMetrics['successfailures'] || {}
  148. groupedMetrics.successfailures[metricName] = groupedMetrics.successfailures[metricName] || {
  149. success: 0,
  150. failures: 0
  151. };
  152. if (successFailures[2] == 'Success') {
  153. groupedMetrics.successfailures[metricName].success = metrics[key];
  154. } else {
  155. groupedMetrics.successfailures[metricName].failures = metrics[key];
  156. }
  157. } else if (numAverages) {
  158. var metricName = numAverages[1];
  159. groupedMetrics.numavgs = groupedMetrics['numavgs'] || {}
  160. groupedMetrics.numavgs[metricName] = groupedMetrics.numavgs[metricName] || {
  161. numOps: 0,
  162. avgTime: 0
  163. };
  164. if (numAverages[2] == 'NumOps') {
  165. groupedMetrics.numavgs[metricName].numOps = metrics[key];
  166. } else {
  167. groupedMetrics.numavgs[metricName].avgTime = metrics[key];
  168. }
  169. } else if (percentileNumOps) {
  170. var metricName = percentileNumOps[1];
  171. var window = percentileNumOps[2];
  172. createPercentageMetrics(metricName, window);
  173. groupedMetrics.percentiles[window][metricName].numOps = metrics[key];
  174. } else if (isIgnoredJmxKeys(key)) {
  175. //ignore
  176. } else {
  177. groupedMetrics.others = groupedMetrics.others || [];
  178. groupedMetrics.others.push({
  179. 'key': key,
  180. 'value': metrics[key]
  181. });
  182. }
  183. }
  184. ctrl.metrics = groupedMetrics;
  185. };
  186. }
  187. });
  188. angular.module('ozone')
  189. .component('tabs', {
  190. transclude: true,
  191. controller: function($scope) {
  192. var ctrl = this;
  193. var panes = this.panes = [];
  194. this.select = function(pane) {
  195. angular.forEach(panes, function(pane) {
  196. pane.selected = false;
  197. });
  198. pane.selected = true;
  199. };
  200. this.addPane = function(pane) {
  201. if (panes.length === 0) {
  202. this.select(pane);
  203. }
  204. panes.push(pane);
  205. };
  206. this.click = function(pane) {
  207. ctrl.select(pane);
  208. }
  209. },
  210. template: '<div class="nav navtabs"><div class="row"><ul' +
  211. ' class="nav nav-pills">' +
  212. '<li ng-repeat="pane in $ctrl.panes" ng-class="{active:pane.selected}">' +
  213. '<a href="" ng-click="$ctrl.click(pane)">{{pane.title}}</a> ' +
  214. '</li> </ul></div><br/><div class="tab-content" ng-transclude></div> </div>'
  215. })
  216. .component('pane', {
  217. transclude: true,
  218. require: {
  219. tabsCtrl: '^tabs'
  220. },
  221. bindings: {
  222. title: '@'
  223. },
  224. controller: function() {
  225. this.$onInit = function() {
  226. this.tabsCtrl.addPane(this);
  227. };
  228. },
  229. template: '<div class="tab-pane" ng-if="$ctrl.selected" ng-transclude></div>'
  230. });
  231. angular.module('ozone').component('navmenu', {
  232. bindings: {
  233. metrics: '<'
  234. },
  235. templateUrl: 'static/templates/menu.html',
  236. controller: function($http) {
  237. var ctrl = this;
  238. ctrl.docs = false;
  239. $http.head("docs/index.html")
  240. .then(function(result) {
  241. ctrl.docs = true;
  242. }, function() {
  243. ctrl.docs = false;
  244. });
  245. }
  246. });
  247. angular.module('ozone').component('config', {
  248. templateUrl: 'static/templates/config.html',
  249. controller: function($scope, $http) {
  250. var ctrl = this;
  251. ctrl.selectedTags = [];
  252. ctrl.configArray = [];
  253. $http.get("conf?cmd=getOzoneTags")
  254. .then(function(response) {
  255. ctrl.tags = response.data;
  256. var excludedTags = ['CBLOCK', 'KSM', 'SCM'];
  257. for (var i = 0; i < excludedTags.length; i++) {
  258. var idx = ctrl.tags.indexOf(excludedTags[i]);
  259. // Remove CBLOCK related properties
  260. if (idx > -1) {
  261. ctrl.tags.splice(idx, 1);
  262. }
  263. }
  264. ctrl.loadAll();
  265. });
  266. ctrl.convertToArray = function(srcObj) {
  267. ctrl.keyTagMap = {};
  268. for (var idx in srcObj) {
  269. //console.log("Adding keys for "+idx)
  270. for (var key in srcObj[idx]) {
  271. if (ctrl.keyTagMap.hasOwnProperty(key)) {
  272. ctrl.keyTagMap[key]['tag'].push(idx);
  273. } else {
  274. var newProp = {};
  275. newProp['name'] = key;
  276. newProp['value'] = srcObj[idx][key];
  277. newProp['tag'] = [];
  278. newProp['tag'].push(idx);
  279. ctrl.keyTagMap[key] = newProp;
  280. }
  281. }
  282. }
  283. }
  284. ctrl.loadAll = function() {
  285. $http.get("conf?cmd=getPropertyByTag&tags=KSM,SCM," + ctrl.tags)
  286. .then(function(response) {
  287. ctrl.convertToArray(response.data);
  288. ctrl.configs = Object.values(ctrl.keyTagMap);
  289. ctrl.component = 'All';
  290. console.log("ajay -> " + JSON.stringify(ctrl.configs));
  291. ctrl.sortBy('name');
  292. });
  293. };
  294. ctrl.filterTags = function() {
  295. if (!ctrl.selectedTags) {
  296. return true;
  297. }
  298. if (ctrl.selectedTags.length < 1 && ctrl.component == 'All') {
  299. return true;
  300. }
  301. ctrl.configs = ctrl.configs.filter(function(item) {
  302. if (ctrl.component != 'All' && (item['tag'].indexOf(ctrl
  303. .component) < 0)) {
  304. console.log(item['name'] + " false tag " + item['tag']);
  305. return false;
  306. }
  307. if (ctrl.selectedTags.length < 1) {
  308. return true;
  309. }
  310. for (var tag in item['tag']) {
  311. tag = item['tag'][tag];
  312. if (ctrl.selectedTags.indexOf(tag) > -1) {
  313. return true;
  314. }
  315. }
  316. return false;
  317. });
  318. };
  319. ctrl.configFilter = function(config) {
  320. return false;
  321. };
  322. ctrl.selected = function(tag) {
  323. return ctrl.selectedTags.includes(tag);
  324. };
  325. ctrl.switchto = function(tag) {
  326. ctrl.component = tag;
  327. ctrl.reloadConfig();
  328. };
  329. ctrl.select = function(tag) {
  330. var tagIdx = ctrl.selectedTags.indexOf(tag);
  331. if (tagIdx > -1) {
  332. ctrl.selectedTags.splice(tagIdx, 1);
  333. } else {
  334. ctrl.selectedTags.push(tag);
  335. }
  336. ctrl.reloadConfig();
  337. };
  338. ctrl.reloadConfig = function() {
  339. ctrl.configs = [];
  340. ctrl.configs = Object.values(ctrl.keyTagMap);
  341. ctrl.filterTags();
  342. };
  343. ctrl.sortBy = function(field) {
  344. ctrl.reverse = (ctrl.propertyName === field) ? !ctrl.reverse : false;
  345. ctrl.propertyName = field;
  346. };
  347. ctrl.allSelected = function(comp) {
  348. //console.log("Adding key for compo ->"+comp)
  349. return ctrl.component == comp;
  350. };
  351. }
  352. });
  353. })();