| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>{{ queue_name }} Charts</title> |
| <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> |
| <link type="text/css" rel="stylesheet" href="/stylesheets/charts.css" /> |
| <script type="text/javascript" src="https://www.google.com/jsapi"></script> |
| <script type="text/javascript"> |
| google.load('visualization', '1.0', {'packages':['corechart']}); |
| google.setOnLoadCallback(function () { |
| |
| function secondsToString(seconds) { |
| var oneSecond = 1; |
| var oneMinute = 60; |
| var oneHour = oneMinute * 60; |
| var oneDay = oneHour * 24; |
| var oneYear = oneDay * 365.25; |
| var unitArray = [ |
| [oneYear, "year"], |
| [oneDay, "day"], |
| [oneHour, "hour"], |
| [oneMinute, "minute"], |
| [oneSecond, "second"], |
| ]; |
| var result = ""; |
| for (var i = 0; i < unitArray.length; i++) { |
| var unit = unitArray[i][0]; |
| if (seconds >= unit) { |
| if (result !== "") { |
| result += " "; |
| } |
| var name = unitArray[i][1]; |
| var number = Math.floor(seconds/unit); |
| result += number + " " + name + (number > 1 ? "s" : ""); |
| seconds %= unit; |
| } |
| } |
| if (result === "") { |
| return "0 seconds"; |
| } |
| return result; |
| } |
| |
| var data, chart, options; |
| |
| var timeString = new Date({{ timestamp }} * 1000).toString(); |
| var timestampDiv = document.getElementById("timestamp"); |
| timestampDiv.innerHTML = "Viewing from " + timeString; |
| |
| options = { |
| legend: {position: "top"}, |
| hAxis: { |
| title: "{{ time_unit_name|capfirst }} Ago", |
| direction: -1, |
| viewWindow: { |
| min: {{ seconds_ago_min }} / {{ time_unit }}, |
| max: {{ seconds_ago_max }} / {{ time_unit }}, |
| }, |
| gridlines: { |
| count: 9, |
| }, |
| }, |
| vAxis: { |
| viewWindow: {min: 0 }, |
| }, |
| lineWidth: 3, |
| }; |
| |
| // CHART 1 |
| options.colors = ["green", "red", "orange"]; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Patches Completed"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn("number", "Patches Waiting"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn("number", "Bots (visible to server)"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addRows([ |
| {% for queue_datum in queue_data %} |
| [ |
| {{ queue_datum.seconds_ago }} / {{ time_unit }}, |
| {{ queue_datum.patches_completed }}, |
| "Patches Completed: " + {{ queue_datum.patches_completed }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago", |
| {{ queue_datum.patches_waiting }}, |
| "Patches Waiting: " + {{ queue_datum.patches_waiting }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago", |
| {{ queue_datum.bots_seen }}, |
| "Bots (visible to server): " + {{ queue_datum.bots_seen }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago", |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.LineChart(document.getElementById('chart1')); |
| chart.draw(data, options); |
| |
| // CHART 2 |
| options.colors = ["blue", "purple"]; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Status Updates"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn("number", "Patch Retries"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addRows([ |
| {% for queue_datum in queue_data %} |
| [ |
| {{ queue_datum.seconds_ago }} / {{ time_unit }}, |
| {{ queue_datum.status_update_count }}, |
| "Status Updates: " + {{ queue_datum.status_update_count }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago", |
| {{ queue_datum.patch_retry_count }}, |
| "Patch Retries: " + {{ queue_datum.patch_retry_count }} + "\n" + secondsToString({{ queue_datum.seconds_ago }}) + " ago", |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.LineChart(document.getElementById('chart2')); |
| chart.draw(data, options); |
| |
| // CHART 3 |
| options.colors = ["brown"]; |
| options.vAxis.title = "Minutes"; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Patch Processing Times"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn({type: "number", role: "interval"}); |
| data.addColumn({type: "number", role: "interval"}); |
| data.addRows([ |
| {% for queue_datum in queue_data %} |
| [ |
| {{ queue_datum.seconds_ago }} / {{ time_unit }}, |
| {{ queue_datum.patch_processing_med }} / 60, |
| "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", |
| {{ queue_datum.patch_processing_min }} / 60, |
| {{ queue_datum.patch_processing_max }} / 60, |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.LineChart(document.getElementById('chart3')); |
| chart.draw(data, options); |
| |
| // CHART 4 |
| options.colors = ["red"]; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Patch Waiting Times"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn({type: "number", role: "interval"}); |
| data.addColumn({type: "number", role: "interval"}); |
| data.addRows([ |
| {% for queue_datum in queue_data %} |
| [ |
| {{ queue_datum.seconds_ago }} / {{ time_unit }}, |
| {{ queue_datum.patch_waiting_med }} / 60, |
| "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", |
| {{ queue_datum.patch_waiting_min }} / 60, |
| {{ queue_datum.patch_waiting_max }} / 60, |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.LineChart(document.getElementById('chart4')); |
| chart.draw(data, options); |
| |
| function postPatchLink (selection) { |
| if (selection.length > 0 && selection[0].row !== undefined) { |
| var attachmentIdArray = [{% for patch_datum in patch_data %}{{ patch_datum.attachment_id }}, {% endfor %}]; |
| var attachmentId = attachmentIdArray[selection[0].row]; |
| var aTag = document.getElementById("selectedPatch"); |
| aTag.innerHTML = aTag.href = "//" + window.location.host + "/patch/" + attachmentId; |
| } |
| } |
| |
| // CHART 5 |
| options.colors = ["brown", "red"]; |
| options.hAxis.title = "{{ time_unit_name|capfirst }} Ago"; |
| options.hAxis.viewWindow.min = {{ seconds_ago_min }} / {{ time_unit }}; |
| options.hAxis.viewWindow.max = {{ seconds_ago_max }} / {{ time_unit }}; |
| delete options.lineWidth; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Process Duration"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn("number", "Wait Duration"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addRows([ |
| {% for patch_datum in patch_data %} |
| [ |
| {{ patch_datum.seconds_ago }} / {{ time_unit }}, |
| {{ patch_datum.process_duration }}, |
| "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago", |
| {{ patch_datum.wait_duration }}, |
| "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago", |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.ScatterChart(document.getElementById('chart5')); |
| var chart5 = chart; |
| google.visualization.events.addListener(chart, "select", function () {postPatchLink(chart5.getSelection());}); |
| chart.draw(data, options); |
| |
| // CHART 6 |
| options.colors = ["blue", "purple"]; |
| delete options.vAxis.title; |
| data = new google.visualization.DataTable(); |
| data.addColumn("number", "<time>"); |
| data.addColumn("number", "Status Updates"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addColumn("number", "Retries"); |
| data.addColumn({type: "string", role: "tooltip"}); |
| data.addRows([ |
| {% for patch_datum in patch_data %} |
| [ |
| {{ patch_datum.seconds_ago }} / {{ time_unit }}, |
| {{ patch_datum.status_update_count }}, |
| "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago", |
| {{ patch_datum.retry_count }}, |
| "Patch {{ patch_datum.attachment_id }}\n" + secondsToString({{ patch_datum.seconds_ago }}) + " ago", |
| ], |
| {% endfor %} |
| ]); |
| chart = new google.visualization.ScatterChart(document.getElementById('chart6')); |
| var chart6 = chart; |
| google.visualization.events.addListener(chart, "select", function () {postPatchLink(chart6.getSelection());}); |
| chart.draw(data, options); |
| }); |
| |
| function setURLParameter (parameterName, newValue) { |
| var split; |
| split = window.location.href.split("?"); |
| var url, parameterArray; |
| url = split[0]; |
| if (split.length > 1) { |
| parameterArray = split[1].split("&"); |
| } else { |
| parameterArray = []; |
| } |
| var setParameter = false; |
| for (var i = 0; i < parameterArray.length; i++) { |
| var currentParameterName = decodeURIComponent(parameterArray[i].split("=")[0]); |
| if (currentParameterName === parameterName) { |
| parameterArray[i] = encodeURIComponent(parameterName) + "=" + encodeURIComponent(newValue); |
| setParameter = true; |
| break; |
| } |
| } |
| if (!setParameter) { |
| parameterArray.push(encodeURIComponent(parameterName) + "=" + encodeURIComponent(newValue)); |
| }console.log(parameterArray); |
| window.location.href = url + "?" + parameterArray.join("&"); |
| } |
| </script> |
| </head> |
| |
| <body> |
| <div class="choices"> |
| {% for single_queue_name in all_queue_names %} |
| {% if single_queue_name == queue_name %} |
| {{ queue_name }} |
| {% else %} |
| {{ single_queue_name|force_escape|queue_charts_link:single_queue_name|safe }} |
| {% endif %} |
| {% if not forloop.last %} | {% endif %} |
| {% endfor %} |
| </div> |
| <h1>{{ queue_name }} Charts</h1> |
| <div>[{{ queue_name|force_escape|queue_status_link:"status"|safe }}]</div> |
| <div id="timestamp"></div> |
| <div class="choices">Viewing range: |
| {% for view_range_choice in view_range_choices %} |
| {% if view_range_choice.view_range == view_range %} |
| {{ view_range_choice.name }} |
| {% else %} |
| <a href="javascript:setURLParameter('view_range', {{ view_range_choice.view_range }})">{{ view_range_choice.name }}</a> |
| {% endif %} |
| {% if not forloop.last %} | {% endif %} |
| {% endfor %} |
| </div> |
| <div class="chart" id="chart1"></div> |
| <div class="chart" id="chart2"></div> |
| <div class="chart" id="chart3"></div> |
| <div class="chart" id="chart4"></div> |
| <div class="chart" id="chart5"></div> |
| <div class="chart" id="chart6"></div> |
| Selected patch: <a id="selectedPatch">(None)</div> |
| </body> |
| </html> |