blob: 953debdbc36b26c6c9e517404bcdd6babe8e7cde [file] [log] [blame]
<!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>