apps_controller.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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. var App = require('app');
  19. var misc = require('utils/misc');
  20. var date = require('utils/date');
  21. App.MainAppsController = Em.ArrayController.extend({
  22. name:'mainAppsController',
  23. content: [],
  24. loaded : false,
  25. loading : false,
  26. /**
  27. * List of users.
  28. * Will be used for filtering in user column.
  29. * Go to App.MainAppsView.userFilterView for more information
  30. */
  31. users: function () {
  32. return this.get('content').mapProperty("userName").uniq().map(function(userName){
  33. return {
  34. name: userName,
  35. checked: false
  36. };
  37. });
  38. }.property('content.length'),
  39. loadRuns:function () {
  40. this.set('loading', true);
  41. var self = this;
  42. //var runsUrl = App.testMode ? "/data/apps/runs.json" : App.apiPrefix + "/jobhistory/workflow?orderBy=startTime&sortDir=DESC&limit=" + App.maxRunsForAppBrowser;
  43. var runsUrl = App.testMode ? "/data/apps/runs.json" : App.apiPrefix + this.get("runUrl");
  44. App.HttpClient.get(runsUrl, App.runsMapper, {
  45. complete:function (jqXHR, textStatus) {
  46. self.set('loading', false);
  47. self.set('loaded', true);
  48. }
  49. });
  50. },
  51. //Pagination Object
  52. paginationObject:{
  53. iTotalDisplayRecords :0,
  54. iTotalRecords:0,
  55. startIndex:0,
  56. endIndex:0
  57. },
  58. /*
  59. Set number of filtered jobs when switching to all jobs
  60. */
  61. iTotalDisplayRecordsObserver:function(){
  62. if(this.get("filterObject.allFilterActivated")){
  63. this.set("filterObject.allFilterActivated", false);
  64. }else{
  65. this.set("filterObject.filteredDisplayRecords",this.get("paginationObject.iTotalDisplayRecords"));
  66. }
  67. }.observes("paginationObject.iTotalDisplayRecords"),
  68. //Filter object
  69. filterObject : Ember.Object.create({
  70. sSearch_0:"",
  71. sSearch_1:"",
  72. sSearch_2:"",
  73. sSearch_3:"",
  74. minJobs:"",
  75. maxJobs:"",
  76. minInputBytes:"",
  77. maxInputBytes:"",
  78. minOutputBytes:"",
  79. maxOutputBytes:"",
  80. minDuration:"",
  81. maxDuration:"",
  82. minStartTime:"",
  83. maxStartTime:"",
  84. sSearch:"",
  85. iDisplayLength:"",
  86. iDisplayStart:"",
  87. iSortCol_0:"",
  88. sSortDir_0:"",
  89. allFilterActivated:false,
  90. filteredDisplayRecords:null,
  91. viewType:"all",
  92. viewTypeClickEvent:false,
  93. /**
  94. * Direct binding to job filter field
  95. */
  96. runType:"",
  97. onRunTypeChange:function(){
  98. if(this.runType == "MapReduce"){
  99. this.set("sSearch_2","mr");
  100. }else if(this.runType == "Hive"){
  101. this.set("sSearch_2","hive");
  102. }else if(this.runType == "Pig"){
  103. this.set("sSearch_2","pig");
  104. }else{
  105. this.set("sSearch_2","");
  106. }
  107. }.observes("runType"),
  108. /**
  109. * Direct binding to job filter field
  110. */
  111. jobs:"",
  112. onJobsChange:function(){
  113. var minMaxTmp = this.parseNumber(this.jobs);
  114. this.set("minJobs", minMaxTmp.min);
  115. this.set("maxJobs", minMaxTmp.max);
  116. }.observes("jobs"),
  117. /**
  118. * Direct binding to Input filter field
  119. */
  120. input:"",
  121. onInputChange:function(){
  122. var minMaxTmp = this.parseBandWidth(this.input);
  123. this.set("minInputBytes", minMaxTmp.min);
  124. this.set("maxInputBytes", minMaxTmp.max);
  125. }.observes("input"),
  126. /**
  127. * Direct binding to Output filter field
  128. */
  129. output:"",
  130. onOutputChange:function(){
  131. var minMaxTmp = this.parseBandWidth(this.output);
  132. this.set("minOutputBytes", minMaxTmp.min);
  133. this.set("maxOutputBytes", minMaxTmp.max);
  134. }.observes("output"),
  135. /**
  136. * Direct binding to Duration filter field
  137. */
  138. duration:"",
  139. onDurationChange:function(){
  140. var minMaxTmp = this.parseDuration(this.duration);
  141. this.set("minDuration", minMaxTmp.min);
  142. this.set("maxDuration", minMaxTmp.max);
  143. }.observes("duration"),
  144. /**
  145. * Direct binding to Run Date filter field
  146. */
  147. runDate:"",
  148. onRunDateChange:function(){
  149. var minMaxTmp = this.parseDate(this.runDate);
  150. this.set("minStartTime", minMaxTmp.min);
  151. this.set("maxStartTime", minMaxTmp.max);
  152. }.observes("runDate"),
  153. parseDuration:function(value){
  154. var tmp={
  155. min:"",
  156. max:""
  157. };
  158. var compareChar = isNaN(value.charAt(0)) ? value.charAt(0) : false;
  159. var compareScale = value.match(/s|m|h/);
  160. compareScale = compareScale ? compareScale[0] : "";
  161. var compareValue = compareChar ? parseFloat(value.substr(1, value.length)) : parseFloat(value.substr(0, value.length));
  162. if(isNaN(compareValue)){
  163. return tmp;
  164. }
  165. switch (compareScale) {
  166. case 'h':
  167. tmp.min = Math.ceil((parseFloat(compareValue)-0.0001)*1000*60*60);
  168. tmp.max = Math.floor((parseFloat(compareValue)+0.0001)*1000*60*60);
  169. break;
  170. case 'm':
  171. tmp.min = Math.ceil((parseFloat(compareValue)-0.001)*1000*60);
  172. tmp.max = Math.floor((parseFloat(compareValue)+0.001)*1000*60);
  173. break;
  174. case 's':
  175. tmp.min = Math.ceil((parseFloat(compareValue)-0.01)*1000);
  176. tmp.max = Math.floor((parseFloat(compareValue)+0.01)*1000);
  177. break;
  178. default:
  179. tmp.min = Math.ceil((parseFloat(compareValue)-0.01)*1000);
  180. tmp.max = Math.floor((parseFloat(compareValue)+0.01)*1000);
  181. }
  182. switch (compareChar) {
  183. case '<':
  184. tmp.min="";
  185. break;
  186. case '>':
  187. tmp.max="";
  188. break;
  189. }
  190. return tmp;
  191. },
  192. parseDate:function(value){
  193. var tmp={
  194. min:"",
  195. max:""
  196. };
  197. var nowTime = App.dateTime();
  198. switch (value){
  199. case 'Any':
  200. break;
  201. case 'Past 1 Day':
  202. tmp.min= nowTime - 86400000;
  203. break;
  204. case 'Past 2 Days':
  205. tmp.min= nowTime - 172800000;
  206. break;
  207. case 'Past 7 Days':
  208. tmp.min= nowTime - 604800000;
  209. break;
  210. case 'Past 14 Days':
  211. tmp.min= nowTime - 1209600000;
  212. break;
  213. case 'Past 30 Days':
  214. tmp.min= nowTime - 2592000000;
  215. break;
  216. case 'Running Now':
  217. tmp.min= nowTime;
  218. break;
  219. }
  220. return tmp;
  221. },
  222. parseBandWidth:function(value){
  223. var tmp={
  224. min:"",
  225. max:""
  226. };
  227. var compareChar = isNaN(value.charAt(0)) ? value.charAt(0) : false;
  228. var compareScale = value.match(/kb|k|mb|m|gb|g/);
  229. compareScale = compareScale ? compareScale[0] : "";
  230. var compareValue = compareChar ? parseFloat(value.substr(1, value.length)) : parseFloat(value.substr(0, value.length));
  231. if(isNaN(compareValue)){
  232. return tmp;
  233. }
  234. switch (compareScale) {
  235. case 'g': case 'gb':
  236. tmp.min = Math.max(1073741824,Math.ceil((compareValue-0.005)*1073741824));
  237. tmp.max = Math.floor((compareValue+0.005)*1073741824);
  238. break;
  239. case 'm': case 'mb':
  240. tmp.min = Math.max(1048576,Math.ceil((compareValue-0.05)*1048576));
  241. tmp.max = Math.min(1073741823,Math.floor((compareValue+0.05)*1048576));
  242. break;
  243. case 'k': case 'kb':
  244. tmp.min = Math.max(1024,Math.ceil((compareValue-0.05)*1024));
  245. tmp.max = Math.min(1048575,Math.floor((compareValue+0.05)*1024));
  246. break;
  247. default:
  248. tmp.min = Math.max(1024,Math.ceil((compareValue-0.05)*1024));
  249. tmp.max = Math.min(1048575,Math.floor((compareValue+0.05)*1024));
  250. }
  251. switch (compareChar) {
  252. case '<':
  253. tmp.min="";
  254. break;
  255. case '>':
  256. tmp.max="";
  257. break;
  258. }
  259. return tmp;
  260. },
  261. parseNumber:function(value){
  262. var tmp={
  263. min:"",
  264. max:""
  265. };
  266. switch (value.charAt(0)) {
  267. case '<':
  268. tmp.max=value.substr(1);
  269. break;
  270. case '>':
  271. tmp.min=value.substr(1);
  272. break;
  273. case '=':
  274. tmp.min=value.substr(1);
  275. tmp.max=value.substr(1);
  276. break;
  277. default:
  278. tmp.min=value;
  279. tmp.max=value;
  280. }
  281. return tmp;
  282. },
  283. /**
  284. * Create link for server request
  285. * @return {String}
  286. */
  287. createAppLink:function(){
  288. var link = "/jobhistory/datatable?";
  289. var arr = [
  290. "sSearch_0", "sSearch_1", "sSearch_2", "sSearch_3", "minJobs",
  291. "maxJobs", "minInputBytes", "maxInputBytes", "minOutputBytes",
  292. "maxOutputBytes", "minDuration", "maxDuration", "minStartTime",
  293. "maxStartTime", "sSearch", "iDisplayLength", "iDisplayStart",
  294. "iSortCol_0", "sSortDir_0"
  295. ];
  296. var notFilterFields = ["iDisplayLength", "iDisplayStart", "iSortCol_0", "sSortDir_0"];
  297. var filtersUsed = false;
  298. for (var n=0; n<arr.length;n++) {
  299. if(this.get(arr[n])){
  300. link += arr[n] + "=" + this.get(arr[n]) + "&";
  301. if (!notFilterFields.contains(arr[n])) {
  302. filtersUsed = true;
  303. }
  304. }
  305. }
  306. link = link.slice(0,link.length-1);
  307. if(!this.get("viewTypeClickEvent")) {
  308. this.set('viewType', filtersUsed?'filtered':'all');
  309. }
  310. return link;
  311. }
  312. }),
  313. /**
  314. * reset all filters in table
  315. *
  316. */
  317. clearFilters: function () {
  318. var obj=this.get("filterObject");
  319. obj.set("sSearch","");
  320. obj.set("sSearch_0","");
  321. obj.set("sSearch_1","");
  322. obj.set("sSearch_2","");
  323. obj.set("sSearch_3","");
  324. obj.set("runType","Any");
  325. obj.set("jobs","");
  326. obj.set("input","");
  327. obj.set("output","");
  328. obj.set("duration","");
  329. obj.set("runDate","Any");
  330. },
  331. runUrl : "/jobhistory/datatable",
  332. runTimeout : null,
  333. valueObserver: function(){
  334. if(this.get('filterObject.iDisplayLength') > this.get('content.length')) {
  335. this.set('filterObject.iDisplayStart', 0);
  336. }
  337. var link = this.get('filterObject').createAppLink();
  338. if(this.get("filterObject.viewType") == "filtered"){
  339. this.set("runUrl", link);
  340. }else{
  341. this.set("runUrl", "/jobhistory/datatable?iDisplayStart=" + this.get('filterObject.iDisplayStart') + "&iDisplayLength=" + this.get('filterObject.iDisplayLength') +
  342. '&iSortCol_0=' + this.get('filterObject.iSortCol_0') + '&sSortDir_0=' + this.get('filterObject.sSortDir_0'));
  343. }
  344. var timeout = this.get('runTimeout');
  345. var self = this;
  346. clearTimeout(timeout);
  347. timeout = setTimeout(function(){
  348. console.log(self.get("runUrl"));
  349. self.loadRuns();
  350. }, 300);
  351. this.set('runTimeout', timeout);
  352. }.observes(
  353. 'filterObject.sSearch_0',
  354. 'filterObject.sSearch_1',
  355. 'filterObject.sSearch_2',
  356. 'filterObject.sSearch_3',
  357. 'filterObject.minJobs',
  358. 'filterObject.maxJobs',
  359. 'filterObject.minInputBytes',
  360. 'filterObject.maxInputBytes',
  361. 'filterObject.minOutputBytes',
  362. 'filterObject.maxOutputBytes',
  363. 'filterObject.minDuration',
  364. 'filterObject.maxDuration',
  365. 'filterObject.minStartTime',
  366. 'filterObject.maxStartTime',
  367. 'filterObject.sSearch',
  368. 'filterObject.iDisplayLength',
  369. 'filterObject.iDisplayStart',
  370. 'filterObject.iSortCol_0',
  371. 'filterObject.sSortDir_0',
  372. 'filterObject.viewType'
  373. ),
  374. serverData: "",
  375. summary: null,
  376. /**
  377. * Observer for summary data from server
  378. */
  379. summaryInfo: function(){
  380. var tmp;
  381. var summary = this.get('serverData');
  382. if(!summary){
  383. tmp = {
  384. 'jobs': {
  385. 'avg': '-',
  386. 'min': '-',
  387. 'max': '-'
  388. },
  389. 'input': {
  390. 'avg': '-',
  391. 'min': '-',
  392. 'max': '-'
  393. },
  394. 'output': {
  395. 'avg': '-',
  396. 'min': '-',
  397. 'max': '-'
  398. },
  399. 'duration': {
  400. 'avg': '-',
  401. 'min': '-',
  402. 'max': '-'
  403. },
  404. 'times': {
  405. 'oldest': '-',
  406. 'youngest': '-'
  407. }
  408. };
  409. }else{
  410. tmp = {
  411. 'jobs': {
  412. 'avg': summary.jobs.avg.toFixed(2),
  413. 'min': summary.jobs.min,
  414. 'max': summary.jobs.max
  415. },
  416. 'input': {
  417. 'avg': misc.formatBandwidth(summary.input.avg),
  418. 'min': misc.formatBandwidth(summary.input.min),
  419. 'max': misc.formatBandwidth(summary.input.max)
  420. },
  421. 'output': {
  422. 'avg': misc.formatBandwidth(summary.output.avg),
  423. 'min': misc.formatBandwidth(summary.output.min),
  424. 'max': misc.formatBandwidth(summary.output.max)
  425. },
  426. 'duration': {
  427. 'avg': date.timingFormat(Math.round(summary.duration.avg)),
  428. 'min': date.timingFormat(summary.duration.min),
  429. 'max': date.timingFormat(summary.duration.max)
  430. },
  431. 'times': {
  432. 'oldest': new Date(summary.times.oldest).toDateString(),
  433. 'youngest': new Date(summary.times.youngest).toDateString()
  434. }
  435. };
  436. }
  437. this.set("summary",tmp);
  438. }.observes('serverData'),
  439. columnsName: Ember.ArrayController.create({
  440. content: [
  441. { name: Em.I18n.t('apps.table.column.appId'), index: 0 },
  442. { name: Em.I18n.t('common.name'), index: 1 },
  443. { name: Em.I18n.t('common.type'), index: 2 },
  444. { name: Em.I18n.t('common.user'), index: 3 },
  445. { name: Em.I18n.t('apps.avgTable.jobs'), index: 4 },
  446. { name: Em.I18n.t('apps.avgTable.input'), index: 5 },
  447. { name: Em.I18n.t('apps.avgTable.output'), index: 6 },
  448. { name: Em.I18n.t('apps.avgTable.duration'), index: 7 },
  449. { name: Em.I18n.t('apps.table.column.runDate'), index: 8 }
  450. ]
  451. })
  452. });