[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class PhabricatorDaemonConsoleController 4 extends PhabricatorDaemonController { 5 6 public function processRequest() { 7 $request = $this->getRequest(); 8 $user = $request->getUser(); 9 10 $window_start = (time() - (60 * 15)); 11 12 // Assume daemons spend about 250ms second in overhead per task acquiring 13 // leases and doing other bookkeeping. This is probably an over-estimation, 14 // but we'd rather show that utilization is too high than too low. 15 $lease_overhead = 0.250; 16 17 $completed = id(new PhabricatorWorkerArchiveTask())->loadAllWhere( 18 'dateModified > %d', 19 $window_start); 20 21 $failed = id(new PhabricatorWorkerActiveTask())->loadAllWhere( 22 'failureTime > %d', 23 $window_start); 24 25 $usage_total = 0; 26 $usage_start = PHP_INT_MAX; 27 28 $completed_info = array(); 29 foreach ($completed as $completed_task) { 30 $class = $completed_task->getTaskClass(); 31 if (empty($completed_info[$class])) { 32 $completed_info[$class] = array( 33 'n' => 0, 34 'duration' => 0, 35 ); 36 } 37 $completed_info[$class]['n']++; 38 $duration = $completed_task->getDuration(); 39 $completed_info[$class]['duration'] += $duration; 40 41 // NOTE: Duration is in microseconds, but we're just using seconds to 42 // compute utilization. 43 $usage_total += $lease_overhead + ($duration / 1000000); 44 $usage_start = min($usage_start, $completed_task->getDateModified()); 45 } 46 47 $completed_info = isort($completed_info, 'n'); 48 49 $rows = array(); 50 foreach ($completed_info as $class => $info) { 51 $rows[] = array( 52 $class, 53 number_format($info['n']), 54 number_format((int)($info['duration'] / $info['n'])).' us', 55 ); 56 } 57 58 if ($failed) { 59 // Add the time it takes to restart the daemons. This includes a guess 60 // about other overhead of 2X. 61 $usage_total += PhutilDaemonOverseer::RESTART_WAIT * count($failed) * 2; 62 foreach ($failed as $failed_task) { 63 $usage_start = min($usage_start, $failed_task->getFailureTime()); 64 } 65 66 $rows[] = array( 67 phutil_tag('em', array(), pht('Temporary Failures')), 68 count($failed), 69 null, 70 ); 71 } 72 73 $logs = id(new PhabricatorDaemonLogQuery()) 74 ->setViewer($user) 75 ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 76 ->setAllowStatusWrites(true) 77 ->execute(); 78 79 $taskmasters = 0; 80 foreach ($logs as $log) { 81 if ($log->getDaemon() == 'PhabricatorTaskmasterDaemon') { 82 $taskmasters++; 83 } 84 } 85 86 if ($taskmasters && $usage_total) { 87 // Total number of wall-time seconds the daemons have been running since 88 // the oldest event. For very short times round up to 15s so we don't 89 // render any ridiculous numbers if you reload the page immediately after 90 // restarting the daemons. 91 $available_time = $taskmasters * max(15, (time() - $usage_start)); 92 93 // Percentage of those wall-time seconds we can account for, which the 94 // daemons spent doing work: 95 $used_time = ($usage_total / $available_time); 96 97 $rows[] = array( 98 phutil_tag('em', array(), pht('Queue Utilization (Approximate)')), 99 sprintf('%.1f%%', 100 * $used_time), 100 null, 101 ); 102 } 103 104 $completed_table = new AphrontTableView($rows); 105 $completed_table->setNoDataString( 106 pht('No tasks have completed in the last 15 minutes.')); 107 $completed_table->setHeaders( 108 array( 109 pht('Class'), 110 pht('Count'), 111 pht('Avg'), 112 )); 113 $completed_table->setColumnClasses( 114 array( 115 'wide', 116 'n', 117 'n', 118 )); 119 120 $completed_panel = new PHUIObjectBoxView(); 121 $completed_panel->setHeaderText( 122 pht('Recently Completed Tasks (Last 15m)')); 123 $completed_panel->appendChild($completed_table); 124 125 $daemon_table = new PhabricatorDaemonLogListView(); 126 $daemon_table->setUser($user); 127 $daemon_table->setDaemonLogs($logs); 128 129 $daemon_panel = new PHUIObjectBoxView(); 130 $daemon_panel->setHeaderText(pht('Active Daemons')); 131 $daemon_panel->appendChild($daemon_table); 132 133 134 $tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere( 135 'leaseOwner IS NOT NULL'); 136 137 $tasks_table = $this->renderTasksTable( 138 $tasks, 139 pht('No tasks are leased by workers.')); 140 141 $leased_panel = id(new PHUIObjectBoxView()) 142 ->setHeaderText(pht('Leased Tasks')) 143 ->appendChild($tasks_table); 144 145 $task_table = new PhabricatorWorkerActiveTask(); 146 $queued = queryfx_all( 147 $task_table->establishConnection('r'), 148 'SELECT taskClass, count(*) N FROM %T GROUP BY taskClass 149 ORDER BY N DESC', 150 $task_table->getTableName()); 151 152 $rows = array(); 153 foreach ($queued as $row) { 154 $rows[] = array( 155 $row['taskClass'], 156 number_format($row['N']), 157 ); 158 } 159 160 $queued_table = new AphrontTableView($rows); 161 $queued_table->setHeaders( 162 array( 163 pht('Class'), 164 pht('Count'), 165 )); 166 $queued_table->setColumnClasses( 167 array( 168 'wide', 169 'n', 170 )); 171 $queued_table->setNoDataString(pht('Task queue is empty.')); 172 173 $queued_panel = new PHUIObjectBoxView(); 174 $queued_panel->setHeaderText(pht('Queued Tasks')); 175 $queued_panel->appendChild($queued_table); 176 177 $upcoming = id(new PhabricatorWorkerLeaseQuery()) 178 ->setLimit(10) 179 ->setSkipLease(true) 180 ->execute(); 181 182 $upcoming_panel = id(new PHUIObjectBoxView()) 183 ->setHeaderText(pht('Next In Queue')) 184 ->appendChild( 185 $this->renderTasksTable($upcoming, pht('Task queue is empty.'))); 186 187 $crumbs = $this->buildApplicationCrumbs(); 188 $crumbs->addTextCrumb(pht('Console')); 189 190 $nav = $this->buildSideNavView(); 191 $nav->selectFilter('/'); 192 $nav->appendChild( 193 array( 194 $crumbs, 195 $completed_panel, 196 $daemon_panel, 197 $queued_panel, 198 $leased_panel, 199 $upcoming_panel, 200 )); 201 202 return $this->buildApplicationPage( 203 $nav, 204 array( 205 'title' => pht('Console'), 206 'device' => false, 207 )); 208 } 209 210 private function renderTasksTable(array $tasks, $nodata) { 211 $rows = array(); 212 foreach ($tasks as $task) { 213 $rows[] = array( 214 $task->getID(), 215 $task->getTaskClass(), 216 $task->getLeaseOwner(), 217 $task->getLeaseExpires() 218 ? phutil_format_relative_time($task->getLeaseExpires() - time()) 219 : '-', 220 $task->getPriority(), 221 $task->getFailureCount(), 222 phutil_tag( 223 'a', 224 array( 225 'href' => '/daemon/task/'.$task->getID().'/', 226 'class' => 'button small grey', 227 ), 228 pht('View Task')), 229 ); 230 } 231 232 $table = new AphrontTableView($rows); 233 $table->setHeaders( 234 array( 235 pht('ID'), 236 pht('Class'), 237 pht('Owner'), 238 pht('Expires'), 239 pht('Priority'), 240 pht('Failures'), 241 '', 242 )); 243 $table->setColumnClasses( 244 array( 245 'n', 246 'wide', 247 '', 248 '', 249 'n', 250 'n', 251 'action', 252 )); 253 $table->setNoDataString($nodata); 254 255 return $table; 256 } 257 258 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |