1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** Random constants. */ 6var MAX_BUILD_STATUS_LENGTH = 50; 7var TICKS_BETWEEN_REFRESHES = 60; 8var NUM_PREVIOUS_BUILDS_TO_SHOW = 3; 9var MAX_MILLISECONDS_TO_WAIT = 5 * 60 * 1000; 10 11/** Parsed JSON data. */ 12var gWaterfallData = []; 13var gStatusData = []; 14var gWaterfallDataIsDirty = true; 15 16/** Global state. */ 17var gTicksUntilRefresh = TICKS_BETWEEN_REFRESHES; 18 19/** Statistics. */ 20var gNumRequestsInFlight = 0; 21var gNumRequestsIgnored = 0; 22var gNumRequestsRetried = 0; 23var gStartTimestamp = 0; 24 25/** Cut the status message down so it doesn't hog the whole screen. */ 26function truncateStatusText(text) { 27 if (text.length > MAX_BUILD_STATUS_LENGTH) { 28 return text.substr(0, MAX_BUILD_STATUS_LENGTH) + '...'; 29 } 30 return text; 31} 32 33/** Queries all of the servers for their latest statuses. */ 34function queryServersForInfo() { 35 for (var index = 0; index < gWaterfallData.length; ++index) { 36 gWaterfallData[index].requestJson(); 37 } 38 39 for (var index = 0; index < gStatusData.length; ++index) { 40 gStatusData[index].requestJson(); 41 } 42} 43 44/** Updates the sidebar's contents. */ 45function updateSidebarHTML() { 46 // Update all of the project info. 47 var divElement = document.getElementById('sidebar-contents'); 48 while (divElement.firstChild) { 49 divElement.removeChild(divElement.firstChild); 50 } 51 52 for (var i = 0; i < gStatusData.length; ++i) { 53 divElement.appendChild(gStatusData[i].createHtml()); 54 } 55 56 // Debugging stats. 57 document.getElementById('num-ticks-until-refresh').innerHTML = 58 gTicksUntilRefresh; 59 document.getElementById('num-requests-in-flight').innerHTML = 60 gNumRequestsInFlight; 61 document.getElementById('num-requests-ignored').innerHTML = 62 gNumRequestsIgnored; 63 document.getElementById('num-requests-retried').innerHTML = 64 gNumRequestsRetried; 65} 66 67/** 68 * Organizes all of the bots by category, then alphabetically within their 69 * categories. 70 */ 71function sortBotNamesByCategory(botInfo) { 72 // Bucket all of the bots according to their category. 73 var allBotNames = Object.keys(botInfo); 74 var bucketedNames = {}; 75 for (var i = 0; i < allBotNames.length; ++i) { 76 var botName = allBotNames[i]; 77 var category = botInfo[botName].category; 78 79 if (!bucketedNames[category]) bucketedNames[category] = []; 80 bucketedNames[category].push(botName); 81 } 82 83 // Alphabetically sort bots within their buckets, then append them to the 84 // current list. 85 var sortedBotNames = []; 86 var allCategories = Object.keys(bucketedNames); 87 allCategories.sort(); 88 for (var i = 0; i < allCategories.length; ++i) { 89 var category = allCategories[i]; 90 var bucketBots = bucketedNames[category]; 91 bucketBots.sort(); 92 93 for (var j = 0; j < bucketBots.length; ++j) { 94 sortedBotNames.push(bucketBots[j]); 95 } 96 } 97 98 return sortedBotNames; 99} 100 101/** Update all the waterfall data. */ 102function updateStatusHTML() { 103 var table = document.getElementById('build-info'); 104 while (table.rows.length > 0) { 105 table.deleteRow(-1); 106 } 107 108 for (var i = 0; i < gWaterfallData.length; ++i) { 109 gWaterfallData[i].updateWaterfallStatusHTML(); 110 } 111} 112 113/** Marks the waterfall data as dirty due to updated filter. */ 114function filterUpdated() { 115 gWaterfallDataIsDirty = true; 116} 117 118/** Update the page content. */ 119function updateContent() { 120 if (--gTicksUntilRefresh <= 0) { 121 gTicksUntilRefresh = TICKS_BETWEEN_REFRESHES; 122 queryServersForInfo(); 123 } 124 125 // Redraw the page content. 126 if (gWaterfallDataIsDirty) { 127 gWaterfallDataIsDirty = false; 128 updateStatusHTML(); 129 130 if (document.getElementById('failure-info')) { 131 updateCorrelationsHTML(); 132 } 133 } 134 updateSidebarHTML(); 135} 136 137/** Initialize all the things. */ 138function initialize() { 139 var gStartTimestamp = new Date().getTime(); 140 141 // Initialize the waterfall pages. 142 for (var i = 0; i < kBuilderPages.length; ++i) { 143 gWaterfallData.push(new WaterfallInfo(kBuilderPages[i])); 144 } 145 146 // Initialize the status pages. 147 for (var i = 0; i < kStatusPages.length; ++i) { 148 gStatusData.push(new StatusPageInfo(kStatusPages[i][0], 149 kStatusPages[i][1])); 150 } 151 152 // Kick off the main loops. 153 queryServersForInfo(); 154 updateStatusHTML(); 155 setInterval('updateContent()', 1000); 156} 157