| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** Random constants. */ |
| var MAX_BUILD_STATUS_LENGTH = 50; |
| var TICKS_BETWEEN_REFRESHES = 60; |
| var NUM_PREVIOUS_BUILDS_TO_SHOW = 3; |
| var MAX_MILLISECONDS_TO_WAIT = 5 * 60 * 1000; |
| |
| /** Parsed JSON data. */ |
| var gWaterfallData = []; |
| var gStatusData = []; |
| var gWaterfallDataIsDirty = true; |
| |
| /** Global state. */ |
| var gTicksUntilRefresh = TICKS_BETWEEN_REFRESHES; |
| |
| /** Statistics. */ |
| var gNumRequestsInFlight = 0; |
| var gNumRequestsIgnored = 0; |
| var gNumRequestsRetried = 0; |
| var gStartTimestamp = 0; |
| |
| /** Cut the status message down so it doesn't hog the whole screen. */ |
| function truncateStatusText(text) { |
| if (text.length > MAX_BUILD_STATUS_LENGTH) { |
| return text.substr(0, MAX_BUILD_STATUS_LENGTH) + '...'; |
| } |
| return text; |
| } |
| |
| /** Queries all of the servers for their latest statuses. */ |
| function queryServersForInfo() { |
| for (var index = 0; index < gWaterfallData.length; ++index) { |
| gWaterfallData[index].requestJson(); |
| } |
| |
| for (var index = 0; index < gStatusData.length; ++index) { |
| gStatusData[index].requestJson(); |
| } |
| } |
| |
| /** Updates the sidebar's contents. */ |
| function updateSidebarHTML() { |
| // Update all of the project info. |
| var divElement = document.getElementById('sidebar-contents'); |
| while (divElement.firstChild) { |
| divElement.removeChild(divElement.firstChild); |
| } |
| |
| for (var i = 0; i < gStatusData.length; ++i) { |
| divElement.appendChild(gStatusData[i].createHtml()); |
| } |
| |
| // Debugging stats. |
| document.getElementById('num-ticks-until-refresh').innerHTML = |
| gTicksUntilRefresh; |
| document.getElementById('num-requests-in-flight').innerHTML = |
| gNumRequestsInFlight; |
| document.getElementById('num-requests-ignored').innerHTML = |
| gNumRequestsIgnored; |
| document.getElementById('num-requests-retried').innerHTML = |
| gNumRequestsRetried; |
| } |
| |
| /** |
| * Organizes all of the bots by category, then alphabetically within their |
| * categories. |
| */ |
| function sortBotNamesByCategory(botInfo) { |
| // Bucket all of the bots according to their category. |
| var allBotNames = Object.keys(botInfo); |
| var bucketedNames = {}; |
| for (var i = 0; i < allBotNames.length; ++i) { |
| var botName = allBotNames[i]; |
| var category = botInfo[botName].category; |
| |
| if (!bucketedNames[category]) bucketedNames[category] = []; |
| bucketedNames[category].push(botName); |
| } |
| |
| // Alphabetically sort bots within their buckets, then append them to the |
| // current list. |
| var sortedBotNames = []; |
| var allCategories = Object.keys(bucketedNames); |
| allCategories.sort(); |
| for (var i = 0; i < allCategories.length; ++i) { |
| var category = allCategories[i]; |
| var bucketBots = bucketedNames[category]; |
| bucketBots.sort(); |
| |
| for (var j = 0; j < bucketBots.length; ++j) { |
| sortedBotNames.push(bucketBots[j]); |
| } |
| } |
| |
| return sortedBotNames; |
| } |
| |
| /** Update all the waterfall data. */ |
| function updateStatusHTML() { |
| var table = document.getElementById('build-info'); |
| while (table.rows.length > 0) { |
| table.deleteRow(-1); |
| } |
| |
| for (var i = 0; i < gWaterfallData.length; ++i) { |
| gWaterfallData[i].updateWaterfallStatusHTML(); |
| } |
| } |
| |
| /** Marks the waterfall data as dirty due to updated filter. */ |
| function filterUpdated() { |
| gWaterfallDataIsDirty = true; |
| } |
| |
| /** Update the page content. */ |
| function updateContent() { |
| if (--gTicksUntilRefresh <= 0) { |
| gTicksUntilRefresh = TICKS_BETWEEN_REFRESHES; |
| queryServersForInfo(); |
| } |
| |
| // Redraw the page content. |
| if (gWaterfallDataIsDirty) { |
| gWaterfallDataIsDirty = false; |
| updateStatusHTML(); |
| |
| if (document.getElementById('failure-info')) { |
| updateCorrelationsHTML(); |
| } |
| } |
| updateSidebarHTML(); |
| } |
| |
| /** Initialize all the things. */ |
| function initialize() { |
| var gStartTimestamp = new Date().getTime(); |
| |
| // Initialize the waterfall pages. |
| for (var i = 0; i < kBuilderPages.length; ++i) { |
| gWaterfallData.push(new WaterfallInfo(kBuilderPages[i])); |
| } |
| |
| // Initialize the status pages. |
| for (var i = 0; i < kStatusPages.length; ++i) { |
| gStatusData.push(new StatusPageInfo(kStatusPages[i][0], |
| kStatusPages[i][1])); |
| } |
| |
| // Kick off the main loops. |
| queryServersForInfo(); |
| updateStatusHTML(); |
| setInterval('updateContent()', 1000); |
| } |