queuecharts.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>{{ queue_name }} Charts</title>
  5. <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
  6. <link type="text/css" rel="stylesheet" href="/stylesheets/charts.css" />
  7. <script type="text/javascript" src="https://www.google.com/jsapi"></script>
  8. <script type="text/javascript">
  9. google.load('visualization', '1.0', {'packages':['corechart']});
  10. google.setOnLoadCallback(function () {
  11. function secondsToString(seconds) {
  12. var oneSecond = 1;
  13. var oneMinute = 60;
  14. var oneHour = oneMinute * 60;
  15. var oneDay = oneHour * 24;
  16. var oneYear = oneDay * 365.25;
  17. var unitArray = [
  18. [oneYear, "year"],
  19. [oneDay, "day"],
  20. [oneHour, "hour"],
  21. [oneMinute, "minute"],
  22. [oneSecond, "second"],
  23. ];
  24. var result = "";
  25. for (var i = 0; i < unitArray.length; i++) {
  26. var unit = unitArray[i][0];
  27. if (seconds >= unit) {
  28. if (result !== "") {
  29. result += " ";
  30. }
  31. var name = unitArray[i][1];
  32. var number = Math.floor(seconds/unit);
  33. result += number + " " + name + (number > 1 ? "s" : "");
  34. seconds %= unit;
  35. }
  36. }
  37. if (result === "") {
  38. return "0 seconds";
  39. }
  40. return result;
  41. }
  42. var data, chart, options;
  43. var timeString = new Date({{ timestamp }} * 1000).toString();
  44. var timestampDiv = document.getElementById("timestamp");
  45. timestampDiv.innerHTML = "Viewing from " + timeString;
  46. options = {
  47. legend: {position: "top"},
  48. hAxis: {
  49. title: "{{ time_unit_name|capfirst }} Ago",
  50. direction: -1,
  51. viewWindow: {
  52. min: {{ seconds_ago_min }} / {{ time_unit }},
  53. max: {{ seconds_ago_max }} / {{ time_unit }},
  54. },
  55. gridlines: {
  56. count: 9,
  57. },
  58. },
  59. vAxis: {
  60. viewWindow: {min: 0 },
  61. },
  62. lineWidth: 3,
  63. };
  64. // CHART 1
  65. options.colors = ["green", "red", "orange"];
  66. data = new google.visualization.DataTable();
  67. data.addColumn("number", "<time>");
  68. data.addColumn("number", "Patches Completed");
  69. data.addColumn({type: "string", role: "tooltip"});
  70. data.addColumn("number", "Patches Waiting");
  71. data.addColumn({type: "string", role: "tooltip"});
  72. data.addColumn("number", "Bots (visible to server)");
  73. data.addColumn({type: "string", role: "tooltip"});
  74. data.addRows([
  75. {% for queue_datum in queue_data %}
  76. [
  77. {{ queue_datum.seconds_ago }} / {{ time_unit }},
  78. {{ queue_datum.patches_completed }},
  79. "Patches Completed: " + {{ queue_datum.patches_completed }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  80. {{ queue_datum.patches_waiting }},
  81. "Patches Waiting: " + {{ queue_datum.patches_waiting }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  82. {{ queue_datum.bots_seen }},
  83. "Bots (visible to server): " + {{ queue_datum.bots_seen }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  84. ],
  85. {% endfor %}
  86. ]);
  87. chart = new google.visualization.LineChart(document.getElementById('chart1'));
  88. chart.draw(data, options);
  89. // CHART 2
  90. options.colors = ["blue", "purple"];
  91. data = new google.visualization.DataTable();
  92. data.addColumn("number", "<time>");
  93. data.addColumn("number", "Status Updates");
  94. data.addColumn({type: "string", role: "tooltip"});
  95. data.addColumn("number", "Patch Retries");
  96. data.addColumn({type: "string", role: "tooltip"});
  97. data.addRows([
  98. {% for queue_datum in queue_data %}
  99. [
  100. {{ queue_datum.seconds_ago }} / {{ time_unit }},
  101. {{ queue_datum.status_update_count }},
  102. "Status Updates: " + {{ queue_datum.status_update_count }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  103. {{ queue_datum.patch_retry_count }},
  104. "Patch Retries: " + {{ queue_datum.patch_retry_count }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  105. ],
  106. {% endfor %}
  107. ]);
  108. chart = new google.visualization.LineChart(document.getElementById('chart2'));
  109. chart.draw(data, options);
  110. // CHART 3
  111. options.colors = ["brown"];
  112. options.vAxis.title = "Minutes";
  113. data = new google.visualization.DataTable();
  114. data.addColumn("number", "<time>");
  115. data.addColumn("number", "Patch Processing Times");
  116. data.addColumn({type: "string", role: "tooltip"});
  117. data.addColumn({type: "number", role: "interval"});
  118. data.addColumn({type: "number", role: "interval"});
  119. data.addRows([
  120. {% for queue_datum in queue_data %}
  121. [
  122. {{ queue_datum.seconds_ago }} / {{ time_unit }},
  123. {{ queue_datum.patch_processing_med }} / 60,
  124. "Patch Processing Times\nMax: " + secondsToString({{ queue_datum.patch_processing_max }}) + "\nMedian: " + secondsToString({{ queue_datum.patch_processing_med }}) + "\nMin: " + secondsToString({{ queue_datum.patch_processing_min }}) + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  125. {{ queue_datum.patch_processing_min }} / 60,
  126. {{ queue_datum.patch_processing_max }} / 60,
  127. ],
  128. {% endfor %}
  129. ]);
  130. chart = new google.visualization.LineChart(document.getElementById('chart3'));
  131. chart.draw(data, options);
  132. // CHART 4
  133. options.colors = ["red"];
  134. data = new google.visualization.DataTable();
  135. data.addColumn("number", "<time>");
  136. data.addColumn("number", "Patch Waiting Times");
  137. data.addColumn({type: "string", role: "tooltip"});
  138. data.addColumn({type: "number", role: "interval"});
  139. data.addColumn({type: "number", role: "interval"});
  140. data.addRows([
  141. {% for queue_datum in queue_data %}
  142. [
  143. {{ queue_datum.seconds_ago }} / {{ time_unit }},
  144. {{ queue_datum.patch_waiting_med }} / 60,
  145. "Patch Waiting Times\nMax: " + secondsToString({{ queue_datum.patch_waiting_max }}) + "\nMedian: " + secondsToString({{ queue_datum.patch_waiting_med }}) + "\nMin: " + secondsToString({{ queue_datum.patch_waiting_min }}) + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago",
  146. {{ queue_datum.patch_waiting_min }} / 60,
  147. {{ queue_datum.patch_waiting_max }} / 60,
  148. ],
  149. {% endfor %}
  150. ]);
  151. chart = new google.visualization.LineChart(document.getElementById('chart4'));
  152. chart.draw(data, options);
  153. function postPatchLink (selection) {
  154. if (selection.length > 0 && selection[0].row !== undefined) {
  155. var attachmentIdArray = [{% for patch_datum in patch_data %}{{ patch_datum.attachment_id }}, {% endfor %}];
  156. var attachmentId = attachmentIdArray[selection[0].row];
  157. var aTag = document.getElementById("selectedPatch");
  158. aTag.innerHTML = aTag.href = "//" + window.location.host + "/patch/" + attachmentId;
  159. }
  160. }
  161. // CHART 5
  162. options.colors = ["brown", "red"];
  163. options.hAxis.title = "{{ time_unit_name|capfirst }} Ago";
  164. options.hAxis.viewWindow.min = {{ seconds_ago_min }} / {{ time_unit }};
  165. options.hAxis.viewWindow.max = {{ seconds_ago_max }} / {{ time_unit }};
  166. delete options.lineWidth;
  167. data = new google.visualization.DataTable();
  168. data.addColumn("number", "<time>");
  169. data.addColumn("number", "Process Duration");
  170. data.addColumn({type: "string", role: "tooltip"});
  171. data.addColumn("number", "Wait Duration");
  172. data.addColumn({type: "string", role: "tooltip"});
  173. data.addRows([
  174. {% for patch_datum in patch_data %}
  175. [
  176. {{ patch_datum.seconds_ago }} / {{ time_unit }},
  177. {{ patch_datum.process_duration }},
  178. "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago",
  179. {{ patch_datum.wait_duration }},
  180. "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago",
  181. ],
  182. {% endfor %}
  183. ]);
  184. chart = new google.visualization.ScatterChart(document.getElementById('chart5'));
  185. var chart5 = chart;
  186. google.visualization.events.addListener(chart, "select", function () {postPatchLink(chart5.getSelection());});
  187. chart.draw(data, options);
  188. // CHART 6
  189. options.colors = ["blue", "purple"];
  190. delete options.vAxis.title;
  191. data = new google.visualization.DataTable();
  192. data.addColumn("number", "<time>");
  193. data.addColumn("number", "Status Updates");
  194. data.addColumn({type: "string", role: "tooltip"});
  195. data.addColumn("number", "Retries");
  196. data.addColumn({type: "string", role: "tooltip"});
  197. data.addRows([
  198. {% for patch_datum in patch_data %}
  199. [
  200. {{ patch_datum.seconds_ago }} / {{ time_unit }},
  201. {{ patch_datum.status_update_count }},
  202. "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago",
  203. {{ patch_datum.retry_count }},
  204. "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago",
  205. ],
  206. {% endfor %}
  207. ]);
  208. chart = new google.visualization.ScatterChart(document.getElementById('chart6'));
  209. var chart6 = chart;
  210. google.visualization.events.addListener(chart, "select", function () {postPatchLink(chart6.getSelection());});
  211. chart.draw(data, options);
  212. });
  213. function setURLParameter (parameterName, newValue) {
  214. var split;
  215. split = window.location.href.split("?");
  216. var url, parameterArray;
  217. url = split[0];
  218. if (split.length > 1) {
  219. parameterArray = split[1].split("&");
  220. } else {
  221. parameterArray = [];
  222. }
  223. var setParameter = false;
  224. for (var i = 0; i < parameterArray.length; i++) {
  225. var currentParameterName = decodeURIComponent(parameterArray[i].split("=")[0]);
  226. if (currentParameterName === parameterName) {
  227. parameterArray[i] = encodeURIComponent(parameterName) + "=" + encodeURIComponent(newValue);
  228. setParameter = true;
  229. break;
  230. }
  231. }
  232. if (!setParameter) {
  233. parameterArray.push(encodeURIComponent(parameterName) + "=" + encodeURIComponent(newValue));
  234. }console.log(parameterArray);
  235. window.location.href = url + "?" + parameterArray.join("&");
  236. }
  237. </script>
  238. </head>
  239. <body>
  240. <div class="choices">
  241. {% for single_queue_name in all_queue_names %}
  242. {% if single_queue_name == queue_name %}
  243. {{ queue_name }}
  244. {% else %}
  245. {{ single_queue_name|force_escape|queue_charts_link:single_queue_name|safe }}
  246. {% endif %}
  247. {% if not forloop.last %} | {% endif %}
  248. {% endfor %}
  249. </div>
  250. <h1>{{ queue_name }} Charts</h1>
  251. <div>[{{ queue_name|force_escape|queue_status_link:"status"|safe }}]</div>
  252. <div id="timestamp"></div>
  253. <div class="choices">Viewing range:
  254. {% for view_range_choice in view_range_choices %}
  255. {% if view_range_choice.view_range == view_range %}
  256. {{ view_range_choice.name }}
  257. {% else %}
  258. <a href="javascript:setURLParameter('view_range', {{ view_range_choice.view_range }})">{{ view_range_choice.name }}</a>
  259. {% endif %}
  260. {% if not forloop.last %} | {% endif %}
  261. {% endfor %}
  262. </div>
  263. <div class="chart" id="chart1"></div>
  264. <div class="chart" id="chart2"></div>
  265. <div class="chart" id="chart3"></div>
  266. <div class="chart" id="chart4"></div>
  267. <div class="chart" id="chart5"></div>
  268. <div class="chart" id="chart6"></div>
  269. Selected patch: <a id="selectedPatch">(None)</div>
  270. </body>
  271. </html>