@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
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move ConduitLogs to ApplicationSearch

Summary:
Ref T9980. Start making this UI more useful and powerful so we can give administrators a better toolset for reacting to API changes.

Fixes T9755. We were logging the caller, just not rendering it properly.

Test Plan: {F1025799}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9755, T9980

Differential Revision: https://secure.phabricator.com/D14779

+176 -147
+2
src/__phutil_library_map__.php
··· 1891 1891 'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php', 1892 1892 'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php', 1893 1893 'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php', 1894 + 'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php', 1894 1895 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php', 1895 1896 'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php', 1896 1897 'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php', ··· 6005 6006 'PhabricatorConduitListController' => 'PhabricatorConduitController', 6006 6007 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 6007 6008 'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6009 + 'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 6008 6010 'PhabricatorConduitMethodCallLog' => array( 6009 6011 'PhabricatorConduitDAO', 6010 6012 'PhabricatorPolicyInterface',
+2 -1
src/applications/conduit/application/PhabricatorConduitApplication.php
··· 48 48 '/conduit/' => array( 49 49 '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorConduitListController', 50 50 'method/(?P<method>[^/]+)/' => 'PhabricatorConduitConsoleController', 51 - 'log/' => 'PhabricatorConduitLogController', 51 + 'log/(?:query/(?P<queryKey>[^/]+)/)?' => 52 + 'PhabricatorConduitLogController', 52 53 'log/view/(?P<view>[^/]+)/' => 'PhabricatorConduitLogController', 53 54 'token/' => 'PhabricatorConduitTokenController', 54 55 'token/edit/(?:(?P<id>\d+)/)?' =>
-8
src/applications/conduit/controller/PhabricatorConduitAPIController.php
··· 110 110 111 111 $time_end = microtime(true); 112 112 113 - $connection_id = null; 114 - if (idx($metadata, 'connectionID')) { 115 - $connection_id = $metadata['connectionID']; 116 - } else if (($method == 'conduit.connect') && $result) { 117 - $connection_id = idx($result, 'connectionID'); 118 - } 119 - 120 113 $log 121 114 ->setCallerPHID( 122 115 isset($conduit_user) 123 116 ? $conduit_user->getPHID() 124 117 : null) 125 - ->setConnectionID($connection_id) 126 118 ->setError((string)$error_code) 127 119 ->setDuration(1000000 * ($time_end - $time_start)); 128 120
+3 -121
src/applications/conduit/controller/PhabricatorConduitLogController.php
··· 4 4 extends PhabricatorConduitController { 5 5 6 6 public function handleRequest(AphrontRequest $request) { 7 - $viewer = $request->getViewer(); 8 - 9 - $conn_table = new PhabricatorConduitConnectionLog(); 10 - $call_table = new PhabricatorConduitMethodCallLog(); 11 - 12 - $conn_r = $call_table->establishConnection('r'); 13 - 14 - $pager = new AphrontCursorPagerView(); 15 - $pager->readFromRequest($request); 16 - $pager->setPageSize(500); 17 - 18 - $query = id(new PhabricatorConduitLogQuery()) 19 - ->setViewer($viewer); 20 - 21 - $methods = $request->getStrList('methods'); 22 - if ($methods) { 23 - $query->withMethods($methods); 24 - } 25 - 26 - $calls = $query->executeWithCursorPager($pager); 27 - 28 - $conn_ids = array_filter(mpull($calls, 'getConnectionID')); 29 - $conns = array(); 30 - if ($conn_ids) { 31 - $conns = $conn_table->loadAllWhere( 32 - 'id IN (%Ld)', 33 - $conn_ids); 34 - } 35 - 36 - $table = $this->renderCallTable($calls, $conns); 37 - $box = id(new PHUIObjectBoxView()) 38 - ->setHeaderText(pht('Call Logs')) 39 - ->setTable($table); 40 - 41 - $crumbs = $this->buildApplicationCrumbs(); 42 - $crumbs->addTextCrumb(pht('Call Logs')); 43 - 44 - return $this->buildApplicationPage( 45 - array( 46 - $crumbs, 47 - $box, 48 - $pager, 49 - ), 50 - array( 51 - 'title' => pht('Conduit Logs'), 52 - )); 53 - } 54 - 55 - private function renderCallTable(array $calls, array $conns) { 56 - assert_instances_of($calls, 'PhabricatorConduitMethodCallLog'); 57 - assert_instances_of($conns, 'PhabricatorConduitConnectionLog'); 58 - 59 - $viewer = $this->getRequest()->getUser(); 60 - 61 - $methods = id(new PhabricatorConduitMethodQuery()) 62 - ->setViewer($viewer) 63 - ->execute(); 64 - $methods = mpull($methods, null, 'getAPIMethodName'); 65 - 66 - $rows = array(); 67 - foreach ($calls as $call) { 68 - $conn = idx($conns, $call->getConnectionID()); 69 - if ($conn) { 70 - $name = $conn->getUserName(); 71 - $client = ' '.pht('(via %s)', $conn->getClient()); 72 - } else { 73 - $name = null; 74 - $client = null; 75 - } 76 - 77 - $method = idx($methods, $call->getMethod()); 78 - if ($method) { 79 - switch ($method->getMethodStatus()) { 80 - case ConduitAPIMethod::METHOD_STATUS_STABLE: 81 - $status = null; 82 - break; 83 - case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: 84 - $status = pht('Unstable'); 85 - break; 86 - case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: 87 - $status = pht('Deprecated'); 88 - break; 89 - } 90 - } else { 91 - $status = pht('Unknown'); 92 - } 93 - 94 - $rows[] = array( 95 - $call->getConnectionID(), 96 - $name, 97 - array($call->getMethod(), $client), 98 - $status, 99 - $call->getError(), 100 - pht('%s us', new PhutilNumber($call->getDuration())), 101 - phabricator_datetime($call->getDateCreated(), $viewer), 102 - ); 103 - } 104 - 105 - $table = id(new AphrontTableView($rows)); 106 - 107 - $table->setHeaders( 108 - array( 109 - pht('Connection'), 110 - pht('User'), 111 - pht('Method'), 112 - pht('Status'), 113 - pht('Error'), 114 - pht('Duration'), 115 - pht('Date'), 116 - )); 117 - $table->setColumnClasses( 118 - array( 119 - '', 120 - '', 121 - 'wide', 122 - '', 123 - '', 124 - 'n', 125 - 'right', 126 - )); 127 - return $table; 7 + return id(new PhabricatorConduitLogSearchEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 128 10 } 129 11 130 12 }
+9 -17
src/applications/conduit/query/PhabricatorConduitLogQuery.php
··· 10 10 return $this; 11 11 } 12 12 13 - protected function loadPage() { 14 - $table = new PhabricatorConduitMethodCallLog(); 15 - $conn_r = $table->establishConnection('r'); 16 - 17 - $data = queryfx_all( 18 - $conn_r, 19 - 'SELECT * FROM %T %Q %Q %Q', 20 - $table->getTableName(), 21 - $this->buildWhereClause($conn_r), 22 - $this->buildOrderClause($conn_r), 23 - $this->buildLimitClause($conn_r)); 13 + public function newResultObject() { 14 + return new PhabricatorConduitMethodCallLog(); 15 + } 24 16 25 - return $table->loadAllFromArray($data); 17 + protected function loadPage() { 18 + return $this->loadStandardPage($this->newResultObject()); 26 19 } 27 20 28 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 29 - $where = array(); 21 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 22 + $where = parent::buildWhereClauseParts($conn); 30 23 31 24 if ($this->methods) { 32 25 $where[] = qsprintf( 33 - $conn_r, 26 + $conn, 34 27 'method IN (%Ls)', 35 28 $this->methods); 36 29 } 37 30 38 - $where[] = $this->buildPagingClause($conn_r); 39 - return $this->formatWhereClause($where); 31 + return $where; 40 32 } 41 33 42 34 public function getQueryApplicationClass() {
+160
src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorConduitLogSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Conduit Logs'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorConduitApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return new PhabricatorConduitLogQuery(); 16 + } 17 + 18 + protected function buildQueryFromParameters(array $map) { 19 + $query = $this->newQuery(); 20 + 21 + if ($map['methods']) { 22 + $query->withMethods($map['methods']); 23 + } 24 + 25 + return $query; 26 + } 27 + 28 + protected function buildCustomSearchFields() { 29 + return array( 30 + id(new PhabricatorSearchStringListField()) 31 + ->setKey('methods') 32 + ->setLabel(pht('Methods')) 33 + ->setDescription(pht('Find calls to specific methods.')), 34 + ); 35 + } 36 + 37 + protected function getURI($path) { 38 + return '/conduit/log/'.$path; 39 + } 40 + 41 + protected function getBuiltinQueryNames() { 42 + $names = array( 43 + 'all' => pht('All Logs'), 44 + ); 45 + 46 + return $names; 47 + } 48 + 49 + public function buildSavedQueryFromBuiltin($query_key) { 50 + $query = $this->newSavedQuery(); 51 + $query->setQueryKey($query_key); 52 + 53 + switch ($query_key) { 54 + case 'all': 55 + return $query; 56 + } 57 + 58 + return parent::buildSavedQueryFromBuiltin($query_key); 59 + } 60 + 61 + protected function renderResultList( 62 + array $logs, 63 + PhabricatorSavedQuery $query, 64 + array $handles) { 65 + assert_instances_of($logs, 'PhabricatorConduitMethodCallLog'); 66 + $viewer = $this->requireViewer(); 67 + 68 + $methods = id(new PhabricatorConduitMethodQuery()) 69 + ->setViewer($viewer) 70 + ->execute(); 71 + $methods = mpull($methods, null, 'getAPIMethodName'); 72 + 73 + Javelin::initBehavior('phabricator-tooltips'); 74 + 75 + $viewer = $this->requireViewer(); 76 + $rows = array(); 77 + foreach ($logs as $log) { 78 + $caller_phid = $log->getCallerPHID(); 79 + 80 + if ($caller_phid) { 81 + $caller = $viewer->renderHandle($caller_phid); 82 + } else { 83 + $caller = null; 84 + } 85 + 86 + $method = idx($methods, $log->getMethod()); 87 + if ($method) { 88 + $method_status = $method->getMethodStatus(); 89 + } else { 90 + $method_status = null; 91 + } 92 + 93 + switch ($method_status) { 94 + case ConduitAPIMethod::METHOD_STATUS_STABLE: 95 + $status = null; 96 + break; 97 + case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: 98 + $status = id(new PHUIIconView()) 99 + ->setIconFont('fa-exclamation-triangle yellow') 100 + ->addSigil('has-tooltip') 101 + ->setMetadata( 102 + array( 103 + 'tip' => pht('Unstable'), 104 + )); 105 + break; 106 + case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: 107 + $status = id(new PHUIIconView()) 108 + ->setIconFont('fa-exclamation-triangle red') 109 + ->addSigil('has-tooltip') 110 + ->setMetadata( 111 + array( 112 + 'tip' => pht('Deprecated'), 113 + )); 114 + break; 115 + default: 116 + $status = id(new PHUIIconView()) 117 + ->setIconFont('fa-question-circle') 118 + ->addSigil('has-tooltip') 119 + ->setMetadata( 120 + array( 121 + 'tip' => pht('Unknown ("%s")', $status), 122 + )); 123 + break; 124 + } 125 + 126 + $rows[] = array( 127 + $status, 128 + $log->getMethod(), 129 + $caller, 130 + $log->getError(), 131 + pht('%s us', new PhutilNumber($log->getDuration())), 132 + phabricator_datetime($log->getDateCreated(), $viewer), 133 + ); 134 + } 135 + 136 + $table = id(new AphrontTableView($rows)) 137 + ->setHeaders( 138 + array( 139 + null, 140 + pht('Method'), 141 + pht('Caller'), 142 + pht('Error'), 143 + pht('Duration'), 144 + pht('Date'), 145 + )) 146 + ->setColumnClasses( 147 + array( 148 + null, 149 + 'pri', 150 + null, 151 + 'wide right', 152 + null, 153 + null, 154 + )); 155 + 156 + return id(new PhabricatorApplicationSearchResultView()) 157 + ->setTable($table) 158 + ->setNoDataString(pht('No matching calls in log.')); 159 + } 160 + }