blob: b6c7a8fc35c63fc3ea727573c662b03d2d9b62d9 [file] [log] [blame]
/*
* Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
var hasBubbles = typeof bubbleQueueServer != "undefined";
var analyzer = new Analyzer;
var allBuilderResultsPseudoQueue = { id: "allBuilderResultsPseudoQueue" };
var allResultsPseudoQueue = { id: "allResultsPseudoQueue" };
var categorizedQueuesByPlatformAndBuildType = {};
var platformsByFamily = {};
for (var i = 0; i < buildbots.length; ++i) {
var buildbot = buildbots[i];
for (var id in buildbot.queues) {
var queue = buildbot.queues[id];
var platform = categorizedQueuesByPlatformAndBuildType[queue.platform];
if (!platform)
platform = categorizedQueuesByPlatformAndBuildType[queue.platform] = {};
if (!platform.builders)
platform.builders = {};
var categoryName;
if (queue.builder)
categoryName = "builders";
else if (queue.tester)
categoryName = queue.testCategory;
else {
console.assert("Unknown queue type.");
continue;
}
category = platform[categoryName];
if (!category)
category = platform[categoryName] = {};
var buildType = queue.debug ? "debug" : "release";
buildQueues = category[buildType];
if (!buildQueues)
buildQueues = category[buildType] = [];
buildQueues.push(queue);
}
}
var testNames = {};
testNames[Buildbot.TestCategory.WebKit2] = "WK2 Tests";
testNames[Buildbot.TestCategory.WebKit1] = "WK1 Tests";
function updateHiddenPlatforms()
{
var hiddenPlatformFamilies = settings.getObject("hiddenPlatformFamilies") || [];
var platformRows = document.querySelectorAll("tr.platform");
for (var i = 0; i < platformRows.length; ++i)
platformRows[i].classList.remove("hidden");
for (var i = 0; i < hiddenPlatformFamilies.length; ++i) {
var platformFamily = hiddenPlatformFamilies[i];
for (var j = 0; j < platformsByFamily[platformFamily].length; ++j) {
var name = platformsByFamily[platformFamily][j];
var platformRow = document.querySelector("tr.platform." + name);
if (platformRow)
platformRow.classList.add("hidden");
}
}
settings.updateToggleButtons();
}
function initPlatformsByFamily()
{
var platforms = Dashboard.sortedPlatforms;
for (var i in platforms) {
// Make sure the platform will be displayed on the page before considering its platform family.
if (!categorizedQueuesByPlatformAndBuildType[platforms[i].name])
continue;
var platformFamily = settings.parsePlatformFamily(platforms[i].name);
if (platformsByFamily[platformFamily])
platformsByFamily[platformFamily].push(platforms[i].name)
else
platformsByFamily[platformFamily] = [platforms[i].name]
}
}
function unhiddenQueues()
{
var hiddenPlatformFamilies = settings.getObject("hiddenPlatformFamilies") || [];
var result = [];
for (var i = 0; i < buildbots.length; ++i) {
var buildbot = buildbots[i];
for (var id in buildbot.queues) {
var queue = buildbot.queues[id];
if (-1 === hiddenPlatformFamilies.indexOf(settings.parsePlatformFamily(queue.platform)))
result.push(queue);
}
}
return result;
}
function allQueues(category)
{
var result = [];
if (category["debug"])
result = result.concat(category["debug"]);
if (category["release"])
result = result.concat(category["release"]);
return result;
}
function buildAggregateTable()
{
var table = document.createElement("table");
table.classList.add("queue-grid");
table.classList.add("aggregate-grid");
var row = document.createElement("tr");
row.classList.add("headers");
header = document.createElement("th");
header.textContent = "Builders";
row.appendChild(header);
header = document.createElement("th");
header.textContent = "All queues";
row.appendChild(header);
table.appendChild(row);
var row = document.createElement("tr");
cell = document.createElement("td");
var view = new MetricsView(analyzer, [allBuilderResultsPseudoQueue]);
cell.appendChild(view.element);
row.appendChild(cell);
cell = document.createElement("td");
var view = new MetricsView(analyzer, [allResultsPseudoQueue]);
cell.appendChild(view.element);
row.appendChild(cell);
table.appendChild(row);
document.body.appendChild(table);
}
function buildQueuesTable()
{
var table = document.createElement("table");
table.classList.add("queue-grid");
table.id = "metrics-queues-table";
var row = document.createElement("tr");
row.classList.add("headers");
var header = document.createElement("th");
row.appendChild(header);
header = document.createElement("th");
header.textContent = "Builders";
row.appendChild(header);
for (var testerKey in Buildbot.TestCategory) {
var header = document.createElement("th");
header.textContent = testNames[Buildbot.TestCategory[testerKey]];
row.appendChild(header);
}
table.appendChild(row);
var platforms = Dashboard.sortedPlatforms;
for (var i in platforms) {
var platform = platforms[i];
var platformQueues = categorizedQueuesByPlatformAndBuildType[platform.name];
if (!platformQueues)
continue;
var row = document.createElement("tr");
row.classList.add("platform");
row.classList.add(platform.name);
var cell = document.createElement("td");
cell.classList.add("logo");
var ringImage = document.createElement("img");
ringImage.classList.add("ring");
ringImage.title = platform.readableName;
cell.appendChild(ringImage);
var logoImage = document.createElement("img");
logoImage.classList.add("logo");
cell.appendChild(logoImage);
row.appendChild(cell);
cell = document.createElement("td");
var view = new MetricsView(analyzer, allQueues(platformQueues.builders));
cell.appendChild(view.element);
row.appendChild(cell);
for (var testerKey in Buildbot.TestCategory) {
var cell = document.createElement("td");
var testerProperty = Buildbot.TestCategory[testerKey];
if (platformQueues[testerProperty]) {
var view = new MetricsView(analyzer, allQueues(platformQueues[testerProperty]));
cell.appendChild(view.element);
}
row.appendChild(cell);
}
table.appendChild(row);
}
document.body.appendChild(table);
return table;
}
function buildBubbleQueuesTable()
{
var table = document.createElement("table");
table.classList.add("queue-grid");
var row = document.createElement("tr");
row.classList.add("headers");
for (id in bubbleQueueServer.queues) {
var header = document.createElement("th");
header.textContent = bubbleQueueServer.queues[id].shortName;
row.appendChild(header);
}
table.appendChild(row);
row = document.createElement("tr");
row.classList.add("platform");
for (id in bubbleQueueServer.queues) {
var cell = document.createElement("td");
var view = new MetricsBubbleView(analyzer, bubbleQueueServer.queues[id]);
cell.appendChild(view.element);
row.appendChild(cell);
}
table.appendChild(row);
document.body.appendChild(table);
return table;
}
function documentReady()
{
var rangePicker = document.createElement("span");
rangePicker.id = "range-picker";
rangePicker.size = 40;
rangePicker.textContent = "Please select a date range";
document.body.appendChild(rangePicker);
$("#range-picker").dateRangePicker({
startOfWeek: navigator.language === "en-us" ? "sunday" : "monday",
endDate: new Date(),
showShortcuts: false,
getValue: function() { return this.textContent; },
setValue: function(s) { this.textContent = s; }
})
.bind('datepicker-apply',function(event,obj)
{
// This message is dispatched even when range hasn't been selected (or only one endpoint was),
// in which case the actual range hasn't changed, and there is nothing to do.
if (isNaN(obj.date1) || isNaN(obj.date2))
return;
var endDate = new Date(new Date(obj.date2).setDate(obj.date2.getDate() + 1));
// FIXME: Support performance bots.
var queues = unhiddenQueues().filter(function(queue) { return queue.builder || queue.tester; });
analyzer.analyze(queues, obj.date1, endDate);
});
var loadingIndicator = document.createElement("div");
loadingIndicator.classList.add("metrics-loading-indicator");
loadingIndicator.textContent = "Loading (first load takes several minutes)\u2026";
document.body.appendChild(loadingIndicator);
analyzer.addEventListener(Analyzer.Event.Starting, function() {
loadingIndicator.style.visibility = "visible";
}, this);
analyzer.addEventListener(Analyzer.Event.Finished, function() {
loadingIndicator.style.visibility = "hidden";
loadingIndicator.textContent = "Loading\u2026"; // Remove the first time warning now.
}, this);
buildAggregateTable();
if (hasBubbles) {
var tablesDivider = document.createElement("div");
tablesDivider.classList.add("tables-divider");
document.body.appendChild(tablesDivider);
buildBubbleQueuesTable();
}
var tablesDivider = document.createElement("div");
tablesDivider.classList.add("tables-divider");
document.body.appendChild(tablesDivider);
var queuesTable = buildQueuesTable();
tablesDivider.style.height = Math.max(tablesDivider.offsetHeight, window.innerHeight - tablesDivider.offsetTop) + "px";
if (settings.available()) {
var settingsButton = document.createElement("div");
settingsButton.addEventListener("click", function () { settings.toggleSettingsDisplay(); });
settingsButton.classList.add("settings");
document.body.appendChild(settingsButton);
var settingsWrapper = document.createElement("div");
settingsWrapper.classList.add("unhide", "hidden", "settingsWrapper")
var platformFamilyToggleWrapper = document.createElement("div");
platformFamilyToggleWrapper.classList.add("unhide", "hidden", "familyToggleWrapper");
var unhideAllButton = document.createElement("div");
unhideAllButton.addEventListener("click", function () { settings.clearHiddenPlatformFamilies(); });
unhideAllButton.classList.add("unhide", "hidden", "platformFamilyToggleButton");
unhideAllButton.setAttribute("id", "all-platformFamilyToggleButton");
unhideAllButton.textContent = "all";
platformFamilyToggleWrapper.appendChild(unhideAllButton);
initPlatformsByFamily();
for (var platformFamily in platformsByFamily) {
var platformFamilyToggle = document.createElement("div");
platformFamilyToggle.addEventListener("click", function () {
settings.toggleHiddenPlatformFamily(this.toString());
}.bind(platformFamily));
platformFamilyToggle.classList.add("unhide", "hidden", "platformFamilyToggleButton");
platformFamilyToggle.setAttribute("id", platformFamily + "-platformFamilyToggleButton");
platformFamilyToggle.textContent = platformFamily;
platformFamilyToggleWrapper.appendChild(platformFamilyToggle);
}
settingsWrapper.appendChild(platformFamilyToggleWrapper);
document.body.appendChild(settingsWrapper);
updateHiddenPlatforms();
settings.addSettingListener("hiddenPlatformFamilies", updateHiddenPlatforms);
settings.addSettingListener("enteredSettings", function() {
$('html, body').stop().animate({
scrollTop: $("#metrics-queues-table").offset().top
}, 200);
});
}
}
document.addEventListener("DOMContentLoaded", documentReady);