@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

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

+136 -103
+5 -3
src/__phutil_library_map__.php
··· 2160 2160 'PhabricatorCustomFieldStringIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStringIndexStorage.php', 2161 2161 'PhabricatorCustomHeaderConfigType' => 'applications/config/custom/PhabricatorCustomHeaderConfigType.php', 2162 2162 'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php', 2163 + 'PhabricatorDaemonBulkJobController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobController.php', 2163 2164 'PhabricatorDaemonBulkJobListController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobListController.php', 2164 2165 'PhabricatorDaemonBulkJobMonitorController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobMonitorController.php', 2165 2166 'PhabricatorDaemonBulkJobViewController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php', ··· 6604 6605 'PhabricatorCustomFieldStringIndexStorage' => 'PhabricatorCustomFieldIndexStorage', 6605 6606 'PhabricatorCustomHeaderConfigType' => 'PhabricatorConfigOptionType', 6606 6607 'PhabricatorDaemon' => 'PhutilDaemon', 6607 - 'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonController', 6608 - 'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonController', 6609 - 'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonController', 6608 + 'PhabricatorDaemonBulkJobController' => 'PhabricatorDaemonController', 6609 + 'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonBulkJobController', 6610 + 'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonBulkJobController', 6611 + 'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonBulkJobController', 6610 6612 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 6611 6613 'PhabricatorDaemonContentSource' => 'PhabricatorContentSource', 6612 6614 'PhabricatorDaemonController' => 'PhabricatorController',
+25
src/applications/daemon/controller/PhabricatorDaemonBulkJobController.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorDaemonBulkJobController 4 + extends PhabricatorDaemonController { 5 + 6 + public function shouldRequireAdmin() { 7 + return false; 8 + } 9 + 10 + public function shouldAllowPublic() { 11 + return true; 12 + } 13 + 14 + public function buildApplicationMenu() { 15 + return $this->newApplicationMenu() 16 + ->setSearchEngine(new PhabricatorWorkerBulkJobSearchEngine()); 17 + } 18 + 19 + protected function buildApplicationCrumbs() { 20 + $crumbs = parent::buildApplicationCrumbs(); 21 + $crumbs->addTextCrumb(pht('Bulk Jobs'), '/daemon/bulk/'); 22 + return $crumbs; 23 + } 24 + 25 + }
+4 -23
src/applications/daemon/controller/PhabricatorDaemonBulkJobListController.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorDaemonBulkJobListController 4 - extends PhabricatorDaemonController { 5 - 6 - public function shouldAllowPublic() { 7 - return true; 8 - } 4 + extends PhabricatorDaemonBulkJobController { 9 5 10 6 public function handleRequest(AphrontRequest $request) { 11 - $controller = id(new PhabricatorApplicationSearchController()) 12 - ->setQueryKey($request->getURIData('queryKey')) 13 - ->setSearchEngine(new PhabricatorWorkerBulkJobSearchEngine()) 14 - ->setNavigation($this->buildSideNavView()); 15 - return $this->delegateToController($controller); 7 + return id(new PhabricatorWorkerBulkJobSearchEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 16 10 } 17 11 18 - protected function buildSideNavView($for_app = false) { 19 - $user = $this->getRequest()->getUser(); 20 - 21 - $nav = new AphrontSideNavFilterView(); 22 - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 23 - 24 - id(new PhabricatorWorkerBulkJobSearchEngine()) 25 - ->setViewer($user) 26 - ->addNavigationItems($nav->getMenu()); 27 - $nav->selectFilter(null); 28 - 29 - return $nav; 30 - } 31 12 }
+1 -5
src/applications/daemon/controller/PhabricatorDaemonBulkJobMonitorController.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorDaemonBulkJobMonitorController 4 - extends PhabricatorDaemonController { 5 - 6 - public function shouldAllowPublic() { 7 - return true; 8 - } 4 + extends PhabricatorDaemonBulkJobController { 9 5 10 6 public function handleRequest(AphrontRequest $request) { 11 7 $viewer = $this->getViewer();
+1 -6
src/applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorDaemonBulkJobViewController 4 - extends PhabricatorDaemonController { 5 - 6 - public function shouldAllowPublic() { 7 - return true; 8 - } 4 + extends PhabricatorDaemonBulkJobController { 9 5 10 6 public function handleRequest(AphrontRequest $request) { 11 7 $viewer = $this->getViewer(); ··· 21 17 $title = pht('Bulk Job %d', $job->getID()); 22 18 23 19 $crumbs = $this->buildApplicationCrumbs(); 24 - $crumbs->addTextCrumb(pht('Bulk Jobs'), '/daemon/bulk/'); 25 20 $crumbs->addTextCrumb($title); 26 21 $crumbs->setBorder(true); 27 22
+6 -7
src/applications/daemon/controller/PhabricatorDaemonConsoleController.php
··· 121 121 ->setHeaderText(pht('Recently Completed Tasks (Last 15m)')) 122 122 ->setTable($completed_table); 123 123 124 - $daemon_table = new PhabricatorDaemonLogListView(); 125 - $daemon_table->setUser($viewer); 126 - $daemon_table->setDaemonLogs($logs); 124 + $daemon_table = id(new PhabricatorDaemonLogListView()) 125 + ->setUser($viewer) 126 + ->setDaemonLogs($logs); 127 127 128 - $daemon_panel = id(new PHUIObjectBoxView()); 129 - $daemon_panel->setHeaderText(pht('Active Daemons')); 130 - $daemon_panel->setObjectList($daemon_table); 131 - 128 + $daemon_panel = id(new PHUIObjectBoxView()) 129 + ->setHeaderText(pht('Active Daemons')) 130 + ->setTable($daemon_table); 132 131 133 132 $tasks = id(new PhabricatorWorkerLeaseQuery()) 134 133 ->setSkipLease(true)
+6 -1
src/applications/daemon/controller/PhabricatorDaemonController.php
··· 1 1 <?php 2 2 3 - abstract class PhabricatorDaemonController extends PhabricatorController { 3 + abstract class PhabricatorDaemonController 4 + extends PhabricatorController { 5 + 6 + public function shouldRequireAdmin() { 7 + return true; 8 + } 4 9 5 10 protected function buildSideNavView() { 6 11 $nav = new AphrontSideNavFilterView();
+5 -5
src/applications/daemon/controller/PhabricatorDaemonLogListController.php
··· 4 4 extends PhabricatorDaemonController { 5 5 6 6 public function handleRequest(AphrontRequest $request) { 7 - $viewer = $request->getViewer(); 7 + $viewer = $this->getViewer(); 8 8 9 9 $pager = new AphrontCursorPagerView(); 10 10 $pager->readFromRequest($request); ··· 14 14 ->setAllowStatusWrites(true) 15 15 ->executeWithCursorPager($pager); 16 16 17 - $daemon_table = new PhabricatorDaemonLogListView(); 18 - $daemon_table->setUser($request->getUser()); 19 - $daemon_table->setDaemonLogs($logs); 17 + $daemon_table = id(new PhabricatorDaemonLogListView()) 18 + ->setViewer($viewer) 19 + ->setDaemonLogs($logs); 20 20 21 21 $box = id(new PHUIObjectBoxView()) 22 22 ->setHeaderText(pht('All Daemons')) 23 - ->appendChild($daemon_table); 23 + ->setTable($daemon_table); 24 24 25 25 $crumbs = $this->buildApplicationCrumbs(); 26 26 $crumbs->addTextCrumb(pht('All Daemons'));
+2 -14
src/applications/daemon/controller/PhabricatorDaemonLogViewController.php
··· 16 16 return new Aphront404Response(); 17 17 } 18 18 19 - $events = id(new PhabricatorDaemonLogEvent())->loadAllWhere( 20 - 'logID = %d ORDER BY id DESC LIMIT 1000', 21 - $log->getID()); 22 - 23 19 $crumbs = $this->buildApplicationCrumbs(); 24 20 $crumbs->addTextCrumb(pht('Daemon %s', $log->getID())); 25 21 $crumbs->setBorder(true); ··· 69 65 70 66 $properties = $this->buildPropertyListView($log); 71 67 72 - $event_view = id(new PhabricatorDaemonLogEventsView()) 73 - ->setUser($viewer) 74 - ->setEvents($events); 75 - 76 - $event_panel = id(new PHUIObjectBoxView()) 77 - ->setHeaderText(pht('Events')) 68 + $object_box = id(new PHUIObjectBoxView()) 69 + ->setHeaderText(pht('Daemon Details')) 78 70 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 79 - ->appendChild($event_view); 80 - 81 - $object_box = id(new PHUIObjectBoxView()) 82 71 ->addPropertyList($properties); 83 72 84 73 $view = id(new PHUITwoColumnView()) 85 74 ->setHeader($header) 86 75 ->setFooter(array( 87 76 $object_box, 88 - $event_panel, 89 77 )); 90 78 91 79 return $this->newPage()
+81 -39
src/applications/daemon/view/PhabricatorDaemonLogListView.php
··· 14 14 $viewer = $this->getViewer(); 15 15 16 16 $rows = array(); 17 + $daemons = $this->daemonLogs; 17 18 18 - $list = new PHUIObjectItemListView(); 19 - $list->setFlush(true); 20 - foreach ($this->daemonLogs as $log) { 21 - $id = $log->getID(); 22 - $epoch = $log->getDateCreated(); 23 - 24 - $item = id(new PHUIObjectItemView()) 25 - ->setObjectName(pht('Daemon %s', $id)) 26 - ->setHeader($log->getDaemon()) 27 - ->setHref("/daemon/log/{$id}/") 28 - ->addIcon('none', phabricator_datetime($epoch, $viewer)); 19 + foreach ($daemons as $daemon) { 20 + $id = $daemon->getID(); 21 + $host = $daemon->getHost(); 22 + $pid = $daemon->getPID(); 23 + $name = phutil_tag( 24 + 'a', 25 + array( 26 + 'href' => "/daemon/log/{$id}/", 27 + ), 28 + $daemon->getDaemon()); 29 29 30 - $status = $log->getStatus(); 30 + $status = $daemon->getStatus(); 31 31 switch ($status) { 32 32 case PhabricatorDaemonLog::STATUS_RUNNING: 33 - $item->setStatusIcon('fa-rocket green'); 34 - $item->addAttribute(pht('This daemon is running.')); 33 + $status_icon = 'fa-rocket green'; 34 + $status_label = pht('Running'); 35 + $status_tip = pht('This daemon is running.'); 35 36 break; 36 37 case PhabricatorDaemonLog::STATUS_DEAD: 37 - $item->setStatusIcon('fa-warning red'); 38 - $item->addAttribute( 39 - pht( 40 - 'This daemon is lost or exited uncleanly, and is presumed '. 41 - 'dead.')); 42 - $item->addIcon('fa-times grey', pht('Dead')); 38 + $status_icon = 'fa-warning red'; 39 + $status_label = pht('Dead'); 40 + $status_tip = pht( 41 + 'This daemon has been lost or exited uncleanly, and is '. 42 + 'presumed dead.'); 43 43 break; 44 44 case PhabricatorDaemonLog::STATUS_EXITING: 45 - $item->addAttribute(pht('This daemon is exiting.')); 46 - $item->addIcon('fa-check', pht('Exiting')); 45 + $status_icon = 'fa-check'; 46 + $status_label = pht('Shutting Down'); 47 + $status_tip = pht('This daemon is shutting down.'); 47 48 break; 48 49 case PhabricatorDaemonLog::STATUS_EXITED: 49 - $item->setDisabled(true); 50 - $item->addAttribute(pht('This daemon exited cleanly.')); 51 - $item->addIcon('fa-check grey', pht('Exited')); 50 + $status_icon = 'fa-check grey'; 51 + $status_label = pht('Exited'); 52 + $status_tip = pht('This daemon exited cleanly.'); 52 53 break; 53 54 case PhabricatorDaemonLog::STATUS_WAIT: 54 - $item->setStatusIcon('fa-clock-o blue'); 55 - $item->addAttribute( 56 - pht( 57 - 'This daemon encountered an error recently and is waiting a '. 58 - 'moment to restart.')); 59 - $item->addIcon('fa-clock-o grey', pht('Waiting')); 55 + $status_icon = 'fa-clock-o blue'; 56 + $status_label = pht('Waiting'); 57 + $status_tip = pht( 58 + 'This daemon encountered an error recently and is waiting a '. 59 + 'moment to restart.'); 60 60 break; 61 61 case PhabricatorDaemonLog::STATUS_UNKNOWN: 62 62 default: 63 - $item->setStatusIcon('fa-warning orange'); 64 - $item->addAttribute( 65 - pht( 66 - 'This daemon has not reported its status recently. It may '. 67 - 'have exited uncleanly.')); 68 - $item->addIcon('fa-warning', pht('Unknown')); 63 + $status_icon = 'fa-warning orange'; 64 + $status_label = pht('Unknown'); 65 + $status_tip = pht( 66 + 'This daemon has not reported its status recently. It may '. 67 + 'have exited uncleanly.'); 69 68 break; 70 69 } 71 70 72 - $list->addItem($item); 71 + $status = phutil_tag( 72 + 'span', 73 + array( 74 + 'sigil' => 'has-tooltip', 75 + 'meta' => array( 76 + 'tip' => $status_tip, 77 + ), 78 + ), 79 + array( 80 + id(new PHUIIconView())->setIcon($status_icon), 81 + ' ', 82 + $status_label, 83 + )); 84 + 85 + $launched = phabricator_datetime($daemon->getDateCreated(), $viewer); 86 + 87 + $rows[] = array( 88 + $id, 89 + $host, 90 + $pid, 91 + $name, 92 + $status, 93 + $launched, 94 + ); 73 95 } 74 96 75 - return $list; 97 + $table = id(new AphrontTableView($rows)) 98 + ->setHeaders( 99 + array( 100 + pht('ID'), 101 + pht('Host'), 102 + pht('PPID'), 103 + pht('Daemon'), 104 + pht('Status'), 105 + pht('Launched'), 106 + )) 107 + ->setColumnClasses( 108 + array( 109 + null, 110 + null, 111 + null, 112 + 'pri', 113 + 'wide', 114 + 'right date', 115 + )); 116 + 117 + return $table; 76 118 } 77 119 78 120 }