graph.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. module.exports = {
  19. uniformSeries: function () {
  20. var series_min_length = 100000000;
  21. for (i=0; i<arguments.length; i++) {
  22. if (arguments[i].length < series_min_length) {
  23. series_min_length = arguments[i].length;
  24. }
  25. }
  26. for (i=0; i<arguments.length; i++) {
  27. if (arguments[i].length > series_min_length) {
  28. arguments[i].length = series_min_length;
  29. }
  30. }
  31. },
  32. /**
  33. * Get min, max for X and Y for provided series
  34. * @param series
  35. * @return {Object}
  36. */
  37. getExtInSeries: function(series) {
  38. var maxY = 0;
  39. var maxX = 0;
  40. var minX = 2147465647; // max timestamp value
  41. var minY = 2147465647;
  42. if (series.length > 0) {
  43. series.forEach(function(item){
  44. if (item.y > maxY) {
  45. maxY = item.y;
  46. }
  47. if (item.y < minY) {
  48. minY = item.y;
  49. }
  50. if (item.x > maxX) {
  51. maxX = item.x;
  52. }
  53. if (item.x < minX) {
  54. minX = item.x;
  55. }
  56. });
  57. }
  58. return {maxX: maxX, minX: minX, maxY: maxY, minY: minY};
  59. },
  60. /**
  61. * Get min, max for x and Y for all provided series
  62. * @param args array of series
  63. * @return {Object}
  64. */
  65. getExtInAllSeries: function(args) {
  66. var maxx = [];
  67. var minx = [];
  68. var maxy = [];
  69. var miny = [];
  70. for (var i = 0; i < args.length; i++) {
  71. var localExt = this.getExtInSeries(args[i]);
  72. maxx.push(localExt.maxX);
  73. minx.push(localExt.minX);
  74. maxy.push(localExt.maxY);
  75. miny.push(localExt.minY);
  76. }
  77. return {
  78. maxX: Math.max.apply(null, maxx),
  79. minX: Math.min.apply(null, minx),
  80. maxY: Math.max.apply(null, maxy),
  81. minY: Math.min.apply(null, miny)
  82. };
  83. },
  84. /**
  85. * Get coordinates for new circle in the graph
  86. * New circle needed to prevent cut on the borders of the graph
  87. * List of arguments - series arrays
  88. * @return {Object}
  89. */
  90. getNewCircle: function() {
  91. var ext = this.getExtInAllSeries(arguments);
  92. var newX;
  93. if (ext.minX != 2147465647) {
  94. newX = ext.maxX + Math.round((ext.maxX - ext.minX) * 0.2);
  95. }
  96. else {
  97. newX = (new Date()).getTime();
  98. }
  99. var newY = ext.maxY * 1.2;
  100. return {
  101. x: newX,
  102. y: newY,
  103. r: 0,
  104. io: 0
  105. };
  106. },
  107. /**
  108. *
  109. * @param map
  110. * @param shuffle
  111. * @param reduce
  112. * @param w
  113. * @param h
  114. * @param element
  115. * @param legend_id
  116. * @param timeline_id
  117. */
  118. drawJobTimeLine:function (map, shuffle, reduce, w, h, element, legend_id, timeline_id) {
  119. map = $.parseJSON(map);
  120. shuffle = $.parseJSON(shuffle);
  121. reduce = $.parseJSON(reduce);
  122. if (!map || !shuffle || !reduce) {
  123. console.warn('drawJobTimeLine');
  124. return;
  125. }
  126. this.uniformSeries(map, reduce, shuffle);
  127. var ext = this.getExtInAllSeries([map, reduce, shuffle]);
  128. var submitTime = ext.minX;
  129. var maxX = ext.maxX; // Used on X-axis time stamps
  130. var graph = new Rickshaw.Graph({
  131. width:w,
  132. height:h,
  133. element:document.querySelector(element),
  134. renderer:'area',
  135. interpolation: 'step-after',
  136. strokeWidth: 2,
  137. stroke:true,
  138. series:[
  139. {
  140. data:map,
  141. color:'green',
  142. name:'maps'
  143. },
  144. {
  145. data:shuffle,
  146. color:'lightblue',
  147. name:'shuffles'
  148. },
  149. {
  150. data:reduce,
  151. color:'steelblue',
  152. name:'reduces'
  153. }
  154. ]
  155. }
  156. );
  157. graph.render();
  158. var legend = new Rickshaw.Graph.Legend({
  159. graph:graph,
  160. element:document.getElementById(legend_id)
  161. });
  162. var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
  163. graph:graph,
  164. legend:legend
  165. });
  166. var order = new Rickshaw.Graph.Behavior.Series.Order({
  167. graph:graph,
  168. legend:legend
  169. });
  170. var highlight = new Rickshaw.Graph.Behavior.Series.Highlight({
  171. graph:graph,
  172. legend:legend
  173. });
  174. var xAxis = new Rickshaw.Graph.Axis.Time({
  175. graph:graph,
  176. timeUnit: {
  177. name: 'Custom',
  178. seconds: Math.round((maxX - submitTime) / 2),
  179. formatter: function(d) { return (new Date(d)).getTime() / 1000 - submitTime + 's'; }
  180. }
  181. });
  182. xAxis.render();
  183. var yAxis = new Rickshaw.Graph.Axis.Y({
  184. orientation: 'left',
  185. element: document.querySelector('#y-axis'),
  186. graph:graph
  187. });
  188. yAxis.render();
  189. var hoverDetail = new Rickshaw.Graph.HoverDetail({
  190. graph:graph,
  191. yFormatter:function (y) {
  192. return Math.floor(y) + " tasks"
  193. }
  194. });
  195. /*var annotator = new Rickshaw.Graph.Annotate({
  196. graph:graph,
  197. //element:document.getElementById(timeline_id)
  198. });*/
  199. },
  200. /**
  201. *
  202. * @param mapNodeLocal
  203. * @param mapRackLocal
  204. * @param mapOffSwitch
  205. * @param reduceOffSwitch
  206. * @param submitTime
  207. * @param w
  208. * @param h
  209. * @param element
  210. * @param legend_id
  211. * @param timeline_id
  212. */
  213. drawJobTasks:function (mapNodeLocal, mapRackLocal, mapOffSwitch, reduceOffSwitch, submitTime, w, h, element, legend_id, timeline_id) {
  214. mapNodeLocal = $.parseJSON(mapNodeLocal);
  215. mapRackLocal = $.parseJSON(mapRackLocal);
  216. mapOffSwitch = $.parseJSON(mapOffSwitch);
  217. reduceOffSwitch = $.parseJSON(reduceOffSwitch);
  218. if (!mapNodeLocal || !mapRackLocal || !mapOffSwitch || !reduceOffSwitch) {
  219. console.warn('drawJobTasks');
  220. return;
  221. }
  222. this.uniformSeries(mapNodeLocal, mapRackLocal, mapOffSwitch, reduceOffSwitch);
  223. var newC = this.getNewCircle(mapNodeLocal, mapRackLocal, mapOffSwitch, reduceOffSwitch);
  224. var ext = this.getExtInAllSeries([mapNodeLocal, mapRackLocal, mapOffSwitch, reduceOffSwitch]);
  225. var maxX = ext.maxX; // Used on X-axis time stamps
  226. mapNodeLocal.push(newC);
  227. mapRackLocal.push(newC);
  228. mapOffSwitch.push(newC);
  229. reduceOffSwitch.push(newC);
  230. var graph = new Rickshaw.Graph({
  231. width:w,
  232. height:h,
  233. element:document.querySelector(element),
  234. renderer:'scatterplot',
  235. stroke:true,
  236. series:[
  237. {
  238. data:mapNodeLocal,
  239. color:'green',
  240. name:'node_local_map'
  241. },
  242. {
  243. data:mapRackLocal,
  244. color:'#66B366',
  245. name:'rack_local_map'
  246. },
  247. {
  248. data:mapOffSwitch,
  249. color:'brown',
  250. name:'off_switch_map'
  251. },
  252. {
  253. data:reduceOffSwitch,
  254. color:'steelblue',
  255. name:'reduce'
  256. }
  257. ]
  258. });
  259. graph.render();
  260. var legend = new Rickshaw.Graph.Legend({
  261. graph:graph,
  262. element:document.getElementById(legend_id)
  263. });
  264. var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
  265. graph:graph,
  266. legend:legend
  267. });
  268. var order = new Rickshaw.Graph.Behavior.Series.Order({
  269. graph:graph,
  270. legend:legend
  271. });
  272. var highlight = new Rickshaw.Graph.Behavior.Series.Highlight({
  273. graph:graph,
  274. legend:legend
  275. });
  276. var ticksTreatment = 'glow';
  277. var xAxis = new Rickshaw.Graph.Axis.Time({
  278. graph:graph,
  279. timeUnit: {
  280. name: 'Custom',
  281. seconds: Math.round((maxX - submitTime) / 2),
  282. formatter: function(d) { return (new Date(d)).getTime() / 1000 - submitTime + 's'; }
  283. },
  284. ticksTreatment:ticksTreatment
  285. });
  286. xAxis.render();
  287. var yAxis = new Rickshaw.Graph.Axis.Y({
  288. graph:graph,
  289. ticksTreatment:ticksTreatment,
  290. orientation: 'left',
  291. element: document.querySelector('#y-axis2'),
  292. tickFormat: function(y) { return y / 1000 + 's' }
  293. });
  294. yAxis.render();
  295. var hoverDetail = new Rickshaw.Graph.HoverDetail({
  296. graph:graph,
  297. xFormatter:function (x) {
  298. return (x - submitTime) + 's'
  299. },
  300. yFormatter:function (y) {
  301. return y / 1000 + 's'
  302. },
  303. formatter:function (series, x, y, formattedX, formattedY, d) {
  304. var bytesFormatter = function(y) {
  305. if (y >= 1125899906842624) { return Math.floor(10 * y / 1125899906842624)/10 + " PB" }
  306. else if (y >= 1099511627776){ return Math.floor(10 * y / 1099511627776)/10 + " TB" }
  307. else if (y >= 1073741824) { return Math.floor(10 * y / 1073741824)/10 + " GB" }
  308. else if (y >= 1048576) { return Math.floor(10 * y / 1048576)/10 + " MB" }
  309. else if (y >= 1024) { return Math.floor(10 * y / 1024)/10 + " KB" }
  310. else { return y + " B"}
  311. };
  312. var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
  313. return swatch + d.value.label +
  314. '<br>Run-time: ' + formattedY + '<br>Wait-time: ' + formattedX +
  315. '<br>I/O: ' + bytesFormatter(d.value.io) + '<br>Status: ' + d.value.status;
  316. }
  317. });
  318. }
  319. }