dfshealth.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. dust.loadSource(dust.compile($('#tmpl-dfshealth').html(), 'dfshealth'));
  21. dust.loadSource(dust.compile($('#tmpl-startup-progress').html(), 'startup-progress'));
  22. dust.loadSource(dust.compile($('#tmpl-datanode').html(), 'datanode-info'));
  23. dust.loadSource(dust.compile($('#tmpl-snapshot').html(), 'snapshot-info'));
  24. function load_overview() {
  25. var BEANS = [
  26. {"name": "nn", "url": "/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo"},
  27. {"name": "nnstat", "url": "/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus"},
  28. {"name": "fs", "url": "/jmx?qry=Hadoop:service=NameNode,name=FSNamesystemState"},
  29. {"name": "mem", "url": "/jmx?qry=java.lang:type=Memory"}
  30. ];
  31. var HELPERS = {
  32. 'helper_fs_max_objects': function (chunk, ctx, bodies, params) {
  33. var o = ctx.current();
  34. if (o.MaxObjects > 0) {
  35. chunk.write('(' + Math.round((o.FilesTotal + o.BlockTotal) / o.MaxObjects * 100) * 100 + ')%');
  36. }
  37. },
  38. 'helper_dir_status': function (chunk, ctx, bodies, params) {
  39. var j = ctx.current();
  40. for (var i in j) {
  41. chunk.write('<tr><td>' + i + '</td><td>' + j[i] + '</td><td>' + params.type + '</td></tr>');
  42. }
  43. }
  44. };
  45. var data = {};
  46. // Workarounds for the fact that JMXJsonServlet returns non-standard JSON strings
  47. function workaround(nn) {
  48. nn.JournalTransactionInfo = JSON.parse(nn.JournalTransactionInfo);
  49. nn.NameJournalStatus = JSON.parse(nn.NameJournalStatus);
  50. nn.NameDirStatuses = JSON.parse(nn.NameDirStatuses);
  51. nn.NodeUsage = JSON.parse(nn.NodeUsage);
  52. nn.CorruptFiles = JSON.parse(nn.CorruptFiles);
  53. return nn;
  54. }
  55. load_json(
  56. BEANS,
  57. guard_with_startup_progress(function(d) {
  58. for (var k in d) {
  59. data[k] = k === 'nn' ? workaround(d[k].beans[0]) : d[k].beans[0];
  60. }
  61. render();
  62. }),
  63. function (url, jqxhr, text, err) {
  64. show_err_msg('<p>Failed to retrieve data from ' + url + ', cause: ' + err + '</p>');
  65. });
  66. function render() {
  67. var base = dust.makeBase(HELPERS);
  68. dust.render('dfshealth', base.push(data), function(err, out) {
  69. $('#tab-overview').html(out);
  70. $('a[href="#tab-datanode"]').click(load_datanode_info);
  71. $('#ui-tabs a[href="#tab-overview"]').tab('show');
  72. });
  73. }
  74. }
  75. $('#ui-tabs a[href="#tab-overview"]').click(load_overview);
  76. function show_err_msg(msg) {
  77. $('#alert-panel-body').html(msg);
  78. $('#alert-panel').show();
  79. }
  80. function ajax_error_handler(url, jqxhr, text, err) {
  81. show_err_msg('<p>Failed to retrieve data from ' + url + ', cause: ' + err + '</p>');
  82. }
  83. function guard_with_startup_progress(fn) {
  84. return function() {
  85. try {
  86. fn.apply(this, arguments);
  87. } catch (err) {
  88. if (err instanceof TypeError) {
  89. show_err_msg('NameNode is still loading. Redirecting to the Startup Progress page.');
  90. load_startup_progress();
  91. }
  92. }
  93. };
  94. }
  95. function load_startup_progress() {
  96. function workaround(r) {
  97. function rename_property(o, s, d) {
  98. if (o[s] !== undefined) {
  99. o[d] = o[s];
  100. delete o[s];
  101. }
  102. }
  103. r.percentComplete *= 100;
  104. $.each(r.phases, function (idx, p) {
  105. p.percentComplete *= 100;
  106. $.each(p.steps, function (idx2, s) {
  107. s.percentComplete *= 100;
  108. // dust.js is confused by these optional keys in nested
  109. // structure, rename them
  110. rename_property(s, "desc", "stepDesc");
  111. rename_property(s, "file", "stepFile");
  112. rename_property(s, "size", "stepSize");
  113. });
  114. });
  115. return r;
  116. }
  117. $.get('/startupProgress', function (resp) {
  118. var data = workaround(resp);
  119. dust.render('startup-progress', data, function(err, out) {
  120. $('#tab-startup-progress').html(out);
  121. $('#ui-tabs a[href="#tab-startup-progress"]').tab('show');
  122. });
  123. }).error(ajax_error_handler);
  124. }
  125. $('#ui-tabs a[href="#tab-startup-progress"]').click(load_startup_progress);
  126. function load_datanode_info() {
  127. function workaround(r) {
  128. function node_map_to_array(nodes) {
  129. var res = [];
  130. for (var n in nodes) {
  131. var p = nodes[n];
  132. p.name = n;
  133. res.push(p);
  134. }
  135. return res;
  136. }
  137. r.LiveNodes = node_map_to_array(JSON.parse(r.LiveNodes));
  138. r.DeadNodes = node_map_to_array(JSON.parse(r.DeadNodes));
  139. r.DecomNodes = node_map_to_array(JSON.parse(r.DecomNodes));
  140. return r;
  141. }
  142. $.get(
  143. '/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo',
  144. guard_with_startup_progress(function (resp) {
  145. var data = workaround(resp.beans[0]);
  146. dust.render('datanode-info', data, function(err, out) {
  147. $('#tab-datanode').html(out);
  148. $('#ui-tabs a[href="#tab-datanode"]').tab('show');
  149. });
  150. })).error(ajax_error_handler);
  151. }
  152. $('a[href="#tab-datanode"]').click(load_datanode_info);
  153. function load_snapshot_info() {
  154. $.get(
  155. '/jmx?qry=Hadoop:service=NameNode,name=FSNamesystemState',
  156. guard_with_startup_progress(function (resp) {
  157. var data = JSON.parse(resp.beans[0].SnapshotStats);
  158. dust.render('snapshot-info', data, function(err, out) {
  159. $('#tab-snapshot').html(out);
  160. $('#ui-tabs a[href="#tab-snapshot"]').tab('show');
  161. });
  162. })).error(ajax_error_handler);
  163. }
  164. $('#ui-tabs a[href="#tab-snapshot"]').click(load_snapshot_info);
  165. function load_page() {
  166. var hash = window.location.hash;
  167. switch(hash) {
  168. case "#tab-datanode":
  169. load_datanode_info();
  170. break;
  171. case "#tab-snapshot":
  172. load_snapshot_info();
  173. break;
  174. case "#tab-startup-progress":
  175. load_startup_progress();
  176. break;
  177. case "#tab-overview":
  178. load_overview();
  179. break;
  180. default:
  181. window.location.hash = "tab-overview";
  182. break;
  183. }
  184. }
  185. load_page();
  186. $(window).bind('hashchange', function () {
  187. load_page();
  188. });
  189. })();