diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1891,6 +1891,7 @@ 'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php', 'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php', 'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php', + 'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php', 'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php', 'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php', @@ -6005,6 +6006,7 @@ 'PhabricatorConduitListController' => 'PhabricatorConduitController', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorConduitMethodCallLog' => array( 'PhabricatorConduitDAO', 'PhabricatorPolicyInterface', diff --git a/src/applications/conduit/application/PhabricatorConduitApplication.php b/src/applications/conduit/application/PhabricatorConduitApplication.php --- a/src/applications/conduit/application/PhabricatorConduitApplication.php +++ b/src/applications/conduit/application/PhabricatorConduitApplication.php @@ -48,7 +48,8 @@ '/conduit/' => array( '(?:query/(?P[^/]+)/)?' => 'PhabricatorConduitListController', 'method/(?P[^/]+)/' => 'PhabricatorConduitConsoleController', - 'log/' => 'PhabricatorConduitLogController', + 'log/(?:query/(?P[^/]+)/)?' => + 'PhabricatorConduitLogController', 'log/view/(?P[^/]+)/' => 'PhabricatorConduitLogController', 'token/' => 'PhabricatorConduitTokenController', 'token/edit/(?:(?P\d+)/)?' => diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php --- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php +++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php @@ -110,19 +110,11 @@ $time_end = microtime(true); - $connection_id = null; - if (idx($metadata, 'connectionID')) { - $connection_id = $metadata['connectionID']; - } else if (($method == 'conduit.connect') && $result) { - $connection_id = idx($result, 'connectionID'); - } - $log ->setCallerPHID( isset($conduit_user) ? $conduit_user->getPHID() : null) - ->setConnectionID($connection_id) ->setError((string)$error_code) ->setDuration(1000000 * ($time_end - $time_start)); diff --git a/src/applications/conduit/controller/PhabricatorConduitLogController.php b/src/applications/conduit/controller/PhabricatorConduitLogController.php --- a/src/applications/conduit/controller/PhabricatorConduitLogController.php +++ b/src/applications/conduit/controller/PhabricatorConduitLogController.php @@ -4,127 +4,9 @@ extends PhabricatorConduitController { public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - - $conn_table = new PhabricatorConduitConnectionLog(); - $call_table = new PhabricatorConduitMethodCallLog(); - - $conn_r = $call_table->establishConnection('r'); - - $pager = new AphrontCursorPagerView(); - $pager->readFromRequest($request); - $pager->setPageSize(500); - - $query = id(new PhabricatorConduitLogQuery()) - ->setViewer($viewer); - - $methods = $request->getStrList('methods'); - if ($methods) { - $query->withMethods($methods); - } - - $calls = $query->executeWithCursorPager($pager); - - $conn_ids = array_filter(mpull($calls, 'getConnectionID')); - $conns = array(); - if ($conn_ids) { - $conns = $conn_table->loadAllWhere( - 'id IN (%Ld)', - $conn_ids); - } - - $table = $this->renderCallTable($calls, $conns); - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Call Logs')) - ->setTable($table); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Call Logs')); - - return $this->buildApplicationPage( - array( - $crumbs, - $box, - $pager, - ), - array( - 'title' => pht('Conduit Logs'), - )); - } - - private function renderCallTable(array $calls, array $conns) { - assert_instances_of($calls, 'PhabricatorConduitMethodCallLog'); - assert_instances_of($conns, 'PhabricatorConduitConnectionLog'); - - $viewer = $this->getRequest()->getUser(); - - $methods = id(new PhabricatorConduitMethodQuery()) - ->setViewer($viewer) - ->execute(); - $methods = mpull($methods, null, 'getAPIMethodName'); - - $rows = array(); - foreach ($calls as $call) { - $conn = idx($conns, $call->getConnectionID()); - if ($conn) { - $name = $conn->getUserName(); - $client = ' '.pht('(via %s)', $conn->getClient()); - } else { - $name = null; - $client = null; - } - - $method = idx($methods, $call->getMethod()); - if ($method) { - switch ($method->getMethodStatus()) { - case ConduitAPIMethod::METHOD_STATUS_STABLE: - $status = null; - break; - case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: - $status = pht('Unstable'); - break; - case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: - $status = pht('Deprecated'); - break; - } - } else { - $status = pht('Unknown'); - } - - $rows[] = array( - $call->getConnectionID(), - $name, - array($call->getMethod(), $client), - $status, - $call->getError(), - pht('%s us', new PhutilNumber($call->getDuration())), - phabricator_datetime($call->getDateCreated(), $viewer), - ); - } - - $table = id(new AphrontTableView($rows)); - - $table->setHeaders( - array( - pht('Connection'), - pht('User'), - pht('Method'), - pht('Status'), - pht('Error'), - pht('Duration'), - pht('Date'), - )); - $table->setColumnClasses( - array( - '', - '', - 'wide', - '', - '', - 'n', - 'right', - )); - return $table; + return id(new PhabricatorConduitLogSearchEngine()) + ->setController($this) + ->buildResponse(); } } diff --git a/src/applications/conduit/query/PhabricatorConduitLogQuery.php b/src/applications/conduit/query/PhabricatorConduitLogQuery.php --- a/src/applications/conduit/query/PhabricatorConduitLogQuery.php +++ b/src/applications/conduit/query/PhabricatorConduitLogQuery.php @@ -10,33 +10,25 @@ return $this; } + public function newResultObject() { + return new PhabricatorConduitMethodCallLog(); + } + protected function loadPage() { - $table = new PhabricatorConduitMethodCallLog(); - $conn_r = $table->establishConnection('r'); - - $data = queryfx_all( - $conn_r, - 'SELECT * FROM %T %Q %Q %Q', - $table->getTableName(), - $this->buildWhereClause($conn_r), - $this->buildOrderClause($conn_r), - $this->buildLimitClause($conn_r)); - - return $table->loadAllFromArray($data); + return $this->loadStandardPage($this->newResultObject()); } - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { - $where = array(); + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = parent::buildWhereClauseParts($conn); if ($this->methods) { $where[] = qsprintf( - $conn_r, + $conn, 'method IN (%Ls)', $this->methods); } - $where[] = $this->buildPagingClause($conn_r); - return $this->formatWhereClause($where); + return $where; } public function getQueryApplicationClass() { diff --git a/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php b/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php @@ -0,0 +1,160 @@ +newQuery(); + + if ($map['methods']) { + $query->withMethods($map['methods']); + } + + return $query; + } + + protected function buildCustomSearchFields() { + return array( + id(new PhabricatorSearchStringListField()) + ->setKey('methods') + ->setLabel(pht('Methods')) + ->setDescription(pht('Find calls to specific methods.')), + ); + } + + protected function getURI($path) { + return '/conduit/log/'.$path; + } + + protected function getBuiltinQueryNames() { + $names = array( + 'all' => pht('All Logs'), + ); + + return $names; + } + + public function buildSavedQueryFromBuiltin($query_key) { + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'all': + return $query; + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + protected function renderResultList( + array $logs, + PhabricatorSavedQuery $query, + array $handles) { + assert_instances_of($logs, 'PhabricatorConduitMethodCallLog'); + $viewer = $this->requireViewer(); + + $methods = id(new PhabricatorConduitMethodQuery()) + ->setViewer($viewer) + ->execute(); + $methods = mpull($methods, null, 'getAPIMethodName'); + + Javelin::initBehavior('phabricator-tooltips'); + + $viewer = $this->requireViewer(); + $rows = array(); + foreach ($logs as $log) { + $caller_phid = $log->getCallerPHID(); + + if ($caller_phid) { + $caller = $viewer->renderHandle($caller_phid); + } else { + $caller = null; + } + + $method = idx($methods, $log->getMethod()); + if ($method) { + $method_status = $method->getMethodStatus(); + } else { + $method_status = null; + } + + switch ($method_status) { + case ConduitAPIMethod::METHOD_STATUS_STABLE: + $status = null; + break; + case ConduitAPIMethod::METHOD_STATUS_UNSTABLE: + $status = id(new PHUIIconView()) + ->setIconFont('fa-exclamation-triangle yellow') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => pht('Unstable'), + )); + break; + case ConduitAPIMethod::METHOD_STATUS_DEPRECATED: + $status = id(new PHUIIconView()) + ->setIconFont('fa-exclamation-triangle red') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => pht('Deprecated'), + )); + break; + default: + $status = id(new PHUIIconView()) + ->setIconFont('fa-question-circle') + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => pht('Unknown ("%s")', $status), + )); + break; + } + + $rows[] = array( + $status, + $log->getMethod(), + $caller, + $log->getError(), + pht('%s us', new PhutilNumber($log->getDuration())), + phabricator_datetime($log->getDateCreated(), $viewer), + ); + } + + $table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + null, + pht('Method'), + pht('Caller'), + pht('Error'), + pht('Duration'), + pht('Date'), + )) + ->setColumnClasses( + array( + null, + 'pri', + null, + 'wide right', + null, + null, + )); + + return id(new PhabricatorApplicationSearchResultView()) + ->setTable($table) + ->setNoDataString(pht('No matching calls in log.')); + } +}