[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/daemon/controller/ -> PhabricatorDaemonConsoleController.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1