mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 22:40:55 +01:00
Improve daemon console for daemons on multiple hosts
Summary: Ref T10756. This: - Fixes T7307. This UI is now admin-only. - Makes the main "running daemons" table more useful for multi-host setups (show where daemons are running). - Removes logs from the web UI: these are sometimes vaguely sensitive and shouldn't be visible. The UI tells you how to get them with `bin/phd log`. - Minor modernization. Test Plan: - As a non-admin, viewed daemons (access error) and bulk jobs (worked great). - Browsed bulk job pages. - Ran a bulk job. - Viewed daemon console. - Viewed task detail / daemon detail / daemon list pages. {F1220516} Reviewers: chad Reviewed By: chad Maniphest Tasks: T7307, T10756 Differential Revision: https://secure.phabricator.com/D15724
This commit is contained in:
parent
42a8776228
commit
d9dd4d427d
10 changed files with 136 additions and 103 deletions
|
@ -2160,6 +2160,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorCustomFieldStringIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStringIndexStorage.php',
|
||||
'PhabricatorCustomHeaderConfigType' => 'applications/config/custom/PhabricatorCustomHeaderConfigType.php',
|
||||
'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php',
|
||||
'PhabricatorDaemonBulkJobController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobController.php',
|
||||
'PhabricatorDaemonBulkJobListController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobListController.php',
|
||||
'PhabricatorDaemonBulkJobMonitorController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobMonitorController.php',
|
||||
'PhabricatorDaemonBulkJobViewController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php',
|
||||
|
@ -6604,9 +6605,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorCustomFieldStringIndexStorage' => 'PhabricatorCustomFieldIndexStorage',
|
||||
'PhabricatorCustomHeaderConfigType' => 'PhabricatorConfigOptionType',
|
||||
'PhabricatorDaemon' => 'PhutilDaemon',
|
||||
'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonBulkJobController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonBulkJobController',
|
||||
'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonBulkJobController',
|
||||
'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonBulkJobController',
|
||||
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonContentSource' => 'PhabricatorContentSource',
|
||||
'PhabricatorDaemonController' => 'PhabricatorController',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorDaemonBulkJobController
|
||||
extends PhabricatorDaemonController {
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function buildApplicationMenu() {
|
||||
return $this->newApplicationMenu()
|
||||
->setSearchEngine(new PhabricatorWorkerBulkJobSearchEngine());
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Bulk Jobs'), '/daemon/bulk/');
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,31 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDaemonBulkJobListController
|
||||
extends PhabricatorDaemonController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
extends PhabricatorDaemonBulkJobController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($request->getURIData('queryKey'))
|
||||
->setSearchEngine(new PhabricatorWorkerBulkJobSearchEngine())
|
||||
->setNavigation($this->buildSideNavView());
|
||||
return $this->delegateToController($controller);
|
||||
return id(new PhabricatorWorkerBulkJobSearchEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildSideNavView($for_app = false) {
|
||||
$user = $this->getRequest()->getUser();
|
||||
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
id(new PhabricatorWorkerBulkJobSearchEngine())
|
||||
->setViewer($user)
|
||||
->addNavigationItems($nav->getMenu());
|
||||
$nav->selectFilter(null);
|
||||
|
||||
return $nav;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDaemonBulkJobMonitorController
|
||||
extends PhabricatorDaemonController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
extends PhabricatorDaemonBulkJobController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorDaemonBulkJobViewController
|
||||
extends PhabricatorDaemonController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
extends PhabricatorDaemonBulkJobController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
@ -21,7 +17,6 @@ final class PhabricatorDaemonBulkJobViewController
|
|||
$title = pht('Bulk Job %d', $job->getID());
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Bulk Jobs'), '/daemon/bulk/');
|
||||
$crumbs->addTextCrumb($title);
|
||||
$crumbs->setBorder(true);
|
||||
|
||||
|
|
|
@ -121,14 +121,13 @@ final class PhabricatorDaemonConsoleController
|
|||
->setHeaderText(pht('Recently Completed Tasks (Last 15m)'))
|
||||
->setTable($completed_table);
|
||||
|
||||
$daemon_table = new PhabricatorDaemonLogListView();
|
||||
$daemon_table->setUser($viewer);
|
||||
$daemon_table->setDaemonLogs($logs);
|
||||
|
||||
$daemon_panel = id(new PHUIObjectBoxView());
|
||||
$daemon_panel->setHeaderText(pht('Active Daemons'));
|
||||
$daemon_panel->setObjectList($daemon_table);
|
||||
$daemon_table = id(new PhabricatorDaemonLogListView())
|
||||
->setUser($viewer)
|
||||
->setDaemonLogs($logs);
|
||||
|
||||
$daemon_panel = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Active Daemons'))
|
||||
->setTable($daemon_table);
|
||||
|
||||
$tasks = id(new PhabricatorWorkerLeaseQuery())
|
||||
->setSkipLease(true)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorDaemonController extends PhabricatorController {
|
||||
abstract class PhabricatorDaemonController
|
||||
extends PhabricatorController {
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function buildSideNavView() {
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
|
|
|
@ -4,7 +4,7 @@ final class PhabricatorDaemonLogListController
|
|||
extends PhabricatorDaemonController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$pager = new AphrontCursorPagerView();
|
||||
$pager->readFromRequest($request);
|
||||
|
@ -14,13 +14,13 @@ final class PhabricatorDaemonLogListController
|
|||
->setAllowStatusWrites(true)
|
||||
->executeWithCursorPager($pager);
|
||||
|
||||
$daemon_table = new PhabricatorDaemonLogListView();
|
||||
$daemon_table->setUser($request->getUser());
|
||||
$daemon_table->setDaemonLogs($logs);
|
||||
$daemon_table = id(new PhabricatorDaemonLogListView())
|
||||
->setViewer($viewer)
|
||||
->setDaemonLogs($logs);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('All Daemons'))
|
||||
->appendChild($daemon_table);
|
||||
->setTable($daemon_table);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('All Daemons'));
|
||||
|
|
|
@ -16,10 +16,6 @@ final class PhabricatorDaemonLogViewController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$events = id(new PhabricatorDaemonLogEvent())->loadAllWhere(
|
||||
'logID = %d ORDER BY id DESC LIMIT 1000',
|
||||
$log->getID());
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Daemon %s', $log->getID()));
|
||||
$crumbs->setBorder(true);
|
||||
|
@ -69,23 +65,15 @@ final class PhabricatorDaemonLogViewController
|
|||
|
||||
$properties = $this->buildPropertyListView($log);
|
||||
|
||||
$event_view = id(new PhabricatorDaemonLogEventsView())
|
||||
->setUser($viewer)
|
||||
->setEvents($events);
|
||||
|
||||
$event_panel = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Events'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->appendChild($event_view);
|
||||
|
||||
$object_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Daemon Details'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(array(
|
||||
$object_box,
|
||||
$event_panel,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
|
|
|
@ -14,65 +14,107 @@ final class PhabricatorDaemonLogListView extends AphrontView {
|
|||
$viewer = $this->getViewer();
|
||||
|
||||
$rows = array();
|
||||
$daemons = $this->daemonLogs;
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$list->setFlush(true);
|
||||
foreach ($this->daemonLogs as $log) {
|
||||
$id = $log->getID();
|
||||
$epoch = $log->getDateCreated();
|
||||
foreach ($daemons as $daemon) {
|
||||
$id = $daemon->getID();
|
||||
$host = $daemon->getHost();
|
||||
$pid = $daemon->getPID();
|
||||
$name = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => "/daemon/log/{$id}/",
|
||||
),
|
||||
$daemon->getDaemon());
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setObjectName(pht('Daemon %s', $id))
|
||||
->setHeader($log->getDaemon())
|
||||
->setHref("/daemon/log/{$id}/")
|
||||
->addIcon('none', phabricator_datetime($epoch, $viewer));
|
||||
|
||||
$status = $log->getStatus();
|
||||
$status = $daemon->getStatus();
|
||||
switch ($status) {
|
||||
case PhabricatorDaemonLog::STATUS_RUNNING:
|
||||
$item->setStatusIcon('fa-rocket green');
|
||||
$item->addAttribute(pht('This daemon is running.'));
|
||||
$status_icon = 'fa-rocket green';
|
||||
$status_label = pht('Running');
|
||||
$status_tip = pht('This daemon is running.');
|
||||
break;
|
||||
case PhabricatorDaemonLog::STATUS_DEAD:
|
||||
$item->setStatusIcon('fa-warning red');
|
||||
$item->addAttribute(
|
||||
pht(
|
||||
'This daemon is lost or exited uncleanly, and is presumed '.
|
||||
'dead.'));
|
||||
$item->addIcon('fa-times grey', pht('Dead'));
|
||||
$status_icon = 'fa-warning red';
|
||||
$status_label = pht('Dead');
|
||||
$status_tip = pht(
|
||||
'This daemon has been lost or exited uncleanly, and is '.
|
||||
'presumed dead.');
|
||||
break;
|
||||
case PhabricatorDaemonLog::STATUS_EXITING:
|
||||
$item->addAttribute(pht('This daemon is exiting.'));
|
||||
$item->addIcon('fa-check', pht('Exiting'));
|
||||
$status_icon = 'fa-check';
|
||||
$status_label = pht('Shutting Down');
|
||||
$status_tip = pht('This daemon is shutting down.');
|
||||
break;
|
||||
case PhabricatorDaemonLog::STATUS_EXITED:
|
||||
$item->setDisabled(true);
|
||||
$item->addAttribute(pht('This daemon exited cleanly.'));
|
||||
$item->addIcon('fa-check grey', pht('Exited'));
|
||||
$status_icon = 'fa-check grey';
|
||||
$status_label = pht('Exited');
|
||||
$status_tip = pht('This daemon exited cleanly.');
|
||||
break;
|
||||
case PhabricatorDaemonLog::STATUS_WAIT:
|
||||
$item->setStatusIcon('fa-clock-o blue');
|
||||
$item->addAttribute(
|
||||
pht(
|
||||
'This daemon encountered an error recently and is waiting a '.
|
||||
'moment to restart.'));
|
||||
$item->addIcon('fa-clock-o grey', pht('Waiting'));
|
||||
$status_icon = 'fa-clock-o blue';
|
||||
$status_label = pht('Waiting');
|
||||
$status_tip = pht(
|
||||
'This daemon encountered an error recently and is waiting a '.
|
||||
'moment to restart.');
|
||||
break;
|
||||
case PhabricatorDaemonLog::STATUS_UNKNOWN:
|
||||
default:
|
||||
$item->setStatusIcon('fa-warning orange');
|
||||
$item->addAttribute(
|
||||
pht(
|
||||
'This daemon has not reported its status recently. It may '.
|
||||
'have exited uncleanly.'));
|
||||
$item->addIcon('fa-warning', pht('Unknown'));
|
||||
$status_icon = 'fa-warning orange';
|
||||
$status_label = pht('Unknown');
|
||||
$status_tip = pht(
|
||||
'This daemon has not reported its status recently. It may '.
|
||||
'have exited uncleanly.');
|
||||
break;
|
||||
}
|
||||
|
||||
$list->addItem($item);
|
||||
$status = phutil_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $status_tip,
|
||||
),
|
||||
),
|
||||
array(
|
||||
id(new PHUIIconView())->setIcon($status_icon),
|
||||
' ',
|
||||
$status_label,
|
||||
));
|
||||
|
||||
$launched = phabricator_datetime($daemon->getDateCreated(), $viewer);
|
||||
|
||||
$rows[] = array(
|
||||
$id,
|
||||
$host,
|
||||
$pid,
|
||||
$name,
|
||||
$status,
|
||||
$launched,
|
||||
);
|
||||
}
|
||||
|
||||
return $list;
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('ID'),
|
||||
pht('Host'),
|
||||
pht('PPID'),
|
||||
pht('Daemon'),
|
||||
pht('Status'),
|
||||
pht('Launched'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'pri',
|
||||
'wide',
|
||||
'right date',
|
||||
));
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue