1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-03 19:31:02 +01:00

Improve Daemon console UI

Summary:
Makes various fixes to the Daemon console UI:

  - Removes timeline, timeline cursors, and timeline-related controllers. This abstraction is all but dead and just waiting on an eventual cleanup effort with Facebook (see T2003). There's no need to inspect or debug it anymore.
  - Instead of showing the 15 most recently launched non-exited daemons, show all the running daemons. With the old rule, "dead" daemons tended to build up at the bottom of the list -- e.g., secure.phabricator.com shows the 7 active daemons, then 8 dead daemons from as far back as Aug 2012. Showing running daemons is far more useful.
  - Simplify the two "Running Daemons" and "All Daemons" subviews into one "All Daemons" subview. The main console now has "running daemons", effectively.
  - Create a "Recently completed tasks" view, which shows how many tasks of each task class have completed in the last 15 minutes and how long they took on average. Understanding how quickly tasks are completing is one of the most common uses of the daemon console, and it's currently almost useless for that. Now that we archive tasks, we can show this information in an easily digestable form.
  - Partially modernize all of the remaining views.

Test Plan: Looked at daemon console.

Reviewers: btrahan, chad, vrana

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2372, T2003

Differential Revision: https://secure.phabricator.com/D4573
This commit is contained in:
epriestley 2013-01-22 12:14:33 -08:00
parent e948073107
commit beaf0bb898
8 changed files with 68 additions and 183 deletions

View file

@ -757,8 +757,6 @@ phutil_register_library_map(array(
'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php',
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php',
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php',
'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/PhabricatorDaemonTimelineConsoleController.php',
'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/PhabricatorDaemonTimelineEventController.php',
'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php',
'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/PhabricatorDefaultSearchEngineSelector.php',
'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php',
@ -2159,8 +2157,6 @@ phutil_register_library_map(array(
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
'PhabricatorDaemonLogListView' => 'AphrontView',
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions',

View file

@ -29,18 +29,15 @@ final class PhabricatorApplicationDaemons extends PhabricatorApplication {
public function getRoutes() {
return array(
'/daemon/' => array(
'' => 'PhabricatorDaemonConsoleController',
'task/(?P<id>[1-9]\d*)/' => 'PhabricatorWorkerTaskDetailController',
'task/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/'
=> 'PhabricatorWorkerTaskUpdateController',
'log/' => array(
'(?P<running>running/)?' => 'PhabricatorDaemonLogListController',
'' => 'PhabricatorDaemonLogListController',
'combined/' => 'PhabricatorDaemonCombinedLogController',
'(?P<id>[1-9]\d*)/' => 'PhabricatorDaemonLogViewController',
),
'timeline/' => 'PhabricatorDaemonTimelineConsoleController',
'timeline/(?P<id>[1-9]\d*)/'
=> 'PhabricatorDaemonTimelineEventController',
'' => 'PhabricatorDaemonConsoleController',
),
);
}

View file

@ -28,6 +28,7 @@ final class PhabricatorDaemonCombinedLogController
$log_panel->setHeader('Combined Daemon Logs');
$log_panel->appendChild($event_view);
$log_panel->appendChild($pager);
$log_panel->setNoBackground();
$nav = $this->buildSideNavView();
$nav->selectFilter('log/combined');

View file

@ -4,19 +4,71 @@ final class PhabricatorDaemonConsoleController
extends PhabricatorDaemonController {
public function processRequest() {
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
'`status` != %s ORDER BY id DESC LIMIT 15', 'exit');
$request = $this->getRequest();
$user = $request->getUser();
$completed = id(new PhabricatorWorkerArchiveTask())->loadAllWhere(
'dateModified > %d',
time() - (60 * 15));
$completed_info = array();
foreach ($completed as $completed_task) {
$class = $completed_task->getTaskClass();
if (empty($completed_info[$class])) {
$completed_info[$class] = array(
'n' => 0,
'duration' => 0,
);
}
$completed_info[$class]['n']++;
$duration = $completed_task->getDuration();
$completed_info[$class]['duration'] += $duration;
}
$completed_info = isort($completed_info, 'n');
$rows = array();
foreach ($completed_info as $class => $info) {
$rows[] = array(
phutil_escape_html($class),
number_format($info['n']),
number_format((int)($info['duration'] / $info['n'])).' us',
);
}
$completed_table = new AphrontTableView($rows);
$completed_table->setNoDataString(
pht('No tasks have completed in the last 15 minutes.'));
$completed_table->setHeaders(
array(
pht('Class'),
pht('Count'),
pht('Avg'),
));
$completed_table->setColumnClasses(
array(
'wide',
'n',
'n',
));
$completed_panel = new AphrontPanelView();
$completed_panel->setHeader(pht('Recently Completed Tasks (15m)'));
$completed_panel->appendChild($completed_table);
$completed_panel->setNoBackground();
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
'`status` = %s ORDER BY id DESC',
'run');
$daemon_table = new PhabricatorDaemonLogListView();
$daemon_table->setUser($user);
$daemon_table->setDaemonLogs($logs);
$daemon_panel = new AphrontPanelView();
$daemon_panel->setHeader('Recently Launched Daemons');
$daemon_panel->setHeader('Active Daemons');
$daemon_panel->appendChild($daemon_table);
$daemon_panel->setNoBackground();
$tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere(
'leaseOwner IS NOT NULL');
@ -63,6 +115,7 @@ final class PhabricatorDaemonConsoleController
$leased_panel = new AphrontPanelView();
$leased_panel->setHeader('Leased Tasks');
$leased_panel->appendChild($leased_table);
$leased_panel->setNoBackground();
$task_table = new PhabricatorWorkerActiveTask();
$queued = queryfx_all(
@ -95,41 +148,14 @@ final class PhabricatorDaemonConsoleController
$queued_panel = new AphrontPanelView();
$queued_panel->setHeader('Queued Tasks');
$queued_panel->appendChild($queued_table);
$cursors = id(new PhabricatorTimelineCursor())
->loadAll();
$rows = array();
foreach ($cursors as $cursor) {
$rows[] = array(
phutil_escape_html($cursor->getName()),
number_format($cursor->getPosition()),
);
}
$cursor_table = new AphrontTableView($rows);
$cursor_table->setHeaders(
array(
'Name',
'Position',
));
$cursor_table->setColumnClasses(
array(
'wide',
'n',
));
$cursor_table->setNoDataString('No timeline cursors exist.');
$cursor_panel = new AphrontPanelView();
$cursor_panel->setHeader('Timeline Cursors');
$cursor_panel->appendChild($cursor_table);
$queued_panel->setNoBackground();
$nav = $this->buildSideNavView();
$nav->selectFilter('');
$nav->selectFilter('/');
$nav->appendChild(
array(
$completed_panel,
$daemon_panel,
$cursor_panel,
$queued_panel,
$leased_panel,
));

View file

@ -7,14 +7,10 @@ abstract class PhabricatorDaemonController extends PhabricatorController {
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel('Daemons');
$nav->addFilter('', 'Console', $this->getApplicationURI());
$nav->addFilter('log/running', 'Running Daemons');
$nav->addFilter('/', 'Console');
$nav->addFilter('log', 'All Daemons');
$nav->addFilter('log/combined', 'Combined Log');
$nav->addLabel('Event Timeline');
$nav->addFilter('timeline', 'Timeline');
return $nav;
}

View file

@ -3,12 +3,6 @@
final class PhabricatorDaemonLogListController
extends PhabricatorDaemonController {
private $running;
public function willProcessRequest(array $data) {
$this->running = !empty($data['running']);
}
public function processRequest() {
$request = $this->getRequest();
@ -16,9 +10,6 @@ final class PhabricatorDaemonLogListController
$pager->setOffset($request->getInt('page'));
$clause = '1 = 1';
if ($this->running) {
$clause = "`status` != 'exit'";
}
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
'%Q ORDER BY id DESC LIMIT %d, %d',
@ -34,18 +25,19 @@ final class PhabricatorDaemonLogListController
$daemon_table->setDaemonLogs($logs);
$daemon_panel = new AphrontPanelView();
$daemon_panel->setHeader('Launched Daemons');
$daemon_panel->setHeader('All Daemons');
$daemon_panel->appendChild($daemon_table);
$daemon_panel->appendChild($pager);
$daemon_panel->setNoBackground();
$nav = $this->buildSideNavView();
$nav->selectFilter($this->running ? 'log/running' : 'log');
$nav->selectFilter('log');
$nav->appendChild($daemon_panel);
return $this->buildApplicationPage(
$nav,
array(
'title' => $this->running ? 'Running Daemons' : 'All Daemons',
'title' => 'All Daemons',
));
}

View file

@ -1,55 +0,0 @@
<?php
final class PhabricatorDaemonTimelineConsoleController
extends PhabricatorDaemonController {
public function processRequest() {
$timeline_table = new PhabricatorTimelineEvent('NULL');
$events = queryfx_all(
$timeline_table->establishConnection('r'),
'SELECT id, type FROM %T ORDER BY id DESC LIMIT 100',
$timeline_table->getTableName());
$rows = array();
foreach ($events as $event) {
$rows[] = array(
phutil_render_tag(
'a',
array(
'href' => '/daemon/timeline/'.$event['id'].'/',
),
$event['id']),
phutil_escape_html($event['type']),
);
}
$event_table = new AphrontTableView($rows);
$event_table->setHeaders(
array(
'ID',
'Type',
));
$event_table->setColumnClasses(
array(
null,
'wide',
));
$event_panel = new AphrontPanelView();
$event_panel->setHeader('Timeline Events');
$event_panel->appendChild($event_table);
$nav = $this->buildSideNavView();
$nav->selectFilter('timeline');
$nav->appendChild($event_panel);
return $this->buildApplicationPage(
$nav,
array(
'title' => 'Timeline',
));
}
}

View file

@ -1,68 +0,0 @@
<?php
final class PhabricatorDaemonTimelineEventController
extends PhabricatorDaemonController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$event = id(new PhabricatorTimelineEvent('NULL'))->load($this->id);
if (!$event) {
return new Aphront404Response();
}
$request = $this->getRequest();
$user = $request->getUser();
if ($event->getDataID()) {
$data = id(new PhabricatorTimelineEventData())->load(
$event->getDataID());
}
if ($data) {
$data = json_encode($data->getEventData());
} else {
$data = 'null';
}
$form = new AphrontFormView();
$form
->setUser($user)
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('ID')
->setValue($event->getID()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Type')
->setValue($event->getType()))
->appendChild(
id(new AphrontFormTextAreaControl())
->setDisabled(true)
->setLabel('Data')
->setValue($data))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/daemon/timeline/'));
$panel = new AphrontPanelView();
$panel->setHeader('Event');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
$nav = $this->buildSideNavView();
$nav->selectFilter('timeline');
$nav->appendChild($panel);
return $this->buildApplicationPage(
$nav,
array(
'title' => 'Timeline Event',
));
}
}