ozone.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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. }], numOps: 0
  126. };
  127. };
  128. var metrics = ctrl.jmxdata;
  129. for (var key in metrics) {
  130. var percentile = key.match(/(.*Time)(\d+s)(\d+th)PercentileLatency/);
  131. var percentileNumOps = key.match(/(.*Time)(\d+s)NumOps/);
  132. var successFailures = key.match(/(.*)(Success|Failures)/);
  133. var numAverages = key.match(/(.*Time)(NumOps|AvgTime)/);
  134. if (percentile) {
  135. var metricName = percentile[1];
  136. var window = percentile[2];
  137. var percentage = percentile[3]
  138. createPercentageMetrics(metricName, window);
  139. groupedMetrics.percentiles[window][metricName].graphdata[0]
  140. .values.push({
  141. label: percentage,
  142. value: metrics[key]
  143. })
  144. } else if (successFailures) {
  145. var metricName = successFailures[1];
  146. groupedMetrics.successfailures = groupedMetrics['successfailures'] || {}
  147. groupedMetrics.successfailures[metricName] = groupedMetrics.successfailures[metricName] || {
  148. success: 0,
  149. failures: 0
  150. };
  151. if (successFailures[2] == 'Success') {
  152. groupedMetrics.successfailures[metricName].success = metrics[key];
  153. } else {
  154. groupedMetrics.successfailures[metricName].failures = metrics[key];
  155. }
  156. } else if (numAverages) {
  157. var metricName = numAverages[1];
  158. groupedMetrics.numavgs = groupedMetrics['numavgs'] || {}
  159. groupedMetrics.numavgs[metricName] = groupedMetrics.numavgs[metricName] || {
  160. numOps: 0,
  161. avgTime: 0
  162. };
  163. if (numAverages[2] == 'NumOps') {
  164. groupedMetrics.numavgs[metricName].numOps = metrics[key];
  165. } else {
  166. groupedMetrics.numavgs[metricName].avgTime = metrics[key];
  167. }
  168. } else if (percentileNumOps) {
  169. var metricName = percentileNumOps[1];
  170. var window = percentileNumOps[2];
  171. createPercentageMetrics(metricName, window);
  172. groupedMetrics.percentiles[window][metricName].numOps = metrics[key];
  173. } else if (isIgnoredJmxKeys(key)) {
  174. //ignore
  175. } else {
  176. groupedMetrics.others = groupedMetrics.others || [];
  177. groupedMetrics.others.push({
  178. 'key': key,
  179. 'value': metrics[key]
  180. });
  181. }
  182. }
  183. ctrl.metrics = groupedMetrics;
  184. };
  185. }
  186. });
  187. angular.module('ozone')
  188. .component('tabs', {
  189. transclude: true,
  190. controller: function ($scope) {
  191. var ctrl = this;
  192. var panes = this.panes = [];
  193. this.select = function (pane) {
  194. angular.forEach(panes, function (pane) {
  195. pane.selected = false;
  196. });
  197. pane.selected = true;
  198. };
  199. this.addPane = function (pane) {
  200. if (panes.length === 0) {
  201. this.select(pane);
  202. }
  203. panes.push(pane);
  204. };
  205. this.click = function(pane) {
  206. ctrl.select(pane);
  207. }
  208. },
  209. template: '<div class="nav navtabs"><div class="row"><ul' +
  210. ' class="nav nav-pills">' +
  211. '<li ng-repeat="pane in $ctrl.panes" ng-class="{active:pane.selected}">' +
  212. '<a href="" ng-click="$ctrl.click(pane)">{{pane.title}}</a> ' +
  213. '</li> </ul></div><br/><div class="tab-content" ng-transclude></div> </div>'
  214. })
  215. .component('pane', {
  216. transclude: true,
  217. require: {
  218. tabsCtrl: '^tabs'
  219. },
  220. bindings: {
  221. title: '@'
  222. },
  223. controller: function () {
  224. this.$onInit = function () {
  225. this.tabsCtrl.addPane(this);
  226. };
  227. },
  228. template: '<div class="tab-pane" ng-if="$ctrl.selected" ng-transclude></div>'
  229. });
  230. angular.module('ozone').component('navmenu', {
  231. bindings: {
  232. metrics: '<'
  233. },
  234. templateUrl: 'static/templates/menu.html',
  235. controller: function ($http) {
  236. var ctrl = this;
  237. ctrl.docs = false;
  238. $http.head("docs/index.html")
  239. .then(function (result) {
  240. ctrl.docs = true;
  241. },function(){
  242. ctrl.docs = false;
  243. });
  244. }
  245. });
  246. angular.module('ozone').component('config', {
  247. templateUrl: 'static/templates/config.html',
  248. controller: function ($scope, $http) {
  249. var ctrl = this;
  250. ctrl.selectedTags = [];
  251. $http.get("conf?cmd=getOzoneTags&group=ozone")
  252. .then(function (response) {
  253. ctrl.tags = response.data;
  254. var excludedTags = ['CBLOCK', 'KSM', 'SCM'];
  255. for (var i = 0; i < excludedTags.length; i++) {
  256. var idx = ctrl.tags.indexOf(excludedTags[i]);
  257. // Remove CBLOCK related properties
  258. if (idx > -1) {
  259. ctrl.tags.splice(idx, 1);
  260. }
  261. }
  262. ctrl.loadAll();
  263. });
  264. ctrl.loadAll = function () {
  265. console.log("Displaying all configs");
  266. $http.get("conf?cmd=getPropertyByTag&tags=" + ctrl.tags + "&group=ozone").then(function (response) {
  267. ctrl.configs = response.data;
  268. console.log(ctrl.configs)
  269. for (var idx in ctrl.configs) {
  270. var tags = []
  271. var parsedTags = ctrl.configs[idx].tag.split(",");
  272. for (var t in parsedTags) {
  273. tags.push(parsedTags[t].trim())
  274. }
  275. ctrl.configs[idx].tag = tags;
  276. };
  277. ctrl.sortBy('name');
  278. });
  279. };
  280. ctrl.tagFilter = function (value, index, array) {
  281. if (!ctrl.selectedTags) {
  282. return true;
  283. }
  284. var selected = true;
  285. for (var idx in ctrl.selectedTags) {
  286. selected = selected && (value.tag.indexOf(ctrl.selectedTags[idx]) > -1);
  287. }
  288. return selected;
  289. };
  290. ctrl.configFilter = function (config) {
  291. return false;
  292. };
  293. ctrl.selected = function (tag) {
  294. return ctrl.selectedTags.includes(tag);
  295. };
  296. ctrl.allSelected = function () {
  297. return ctrl.selectedTags.indexOf('SCM') == -1
  298. && ctrl.selectedTags.indexOf('KSM') == -1
  299. };
  300. ctrl.switchto = function (tag) {
  301. var tags = ctrl.selectedTags.filter(function (item) {
  302. return item != 'KSM' && item != 'SCM';
  303. });
  304. if (tag) {
  305. tags.push(tag);
  306. }
  307. ctrl.selectedTags = tags;
  308. };
  309. ctrl.select = function (tag) {
  310. var tagIdx = ctrl.selectedTags.indexOf(tag);
  311. if (tagIdx > -1) {
  312. ctrl.selectedTags = ctrl.selectedTags.filter(function (item) {
  313. return item != tag;
  314. });
  315. } else {
  316. ctrl.selectedTags.push(tag);
  317. }
  318. console.log("Tags selected:" + ctrl.selectedTags);
  319. };
  320. ctrl.sortBy = function (propertyName) {
  321. ctrl.reverse = (ctrl.propertyName === propertyName) ? !ctrl.reverse : false;
  322. ctrl.propertyName = propertyName;
  323. };
  324. }
  325. });
  326. })();