mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Track daemon unique IDs in Phabricator daemon logs
Summary: Ref T7352. We were previously identifying things by `<daemonClass, overseerPID, startTime>` but that's not unique in a world where one overseer can run multiple daemons. We already have an internal "daemonID", it just doesn't get written into the DB right now. Start writing it, then use it to clean up `phd status`. Test Plan: Ran `phd status`, got more accurate/useful output than previously. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7352 Differential Revision: https://secure.phabricator.com/D11865
This commit is contained in:
parent
ef22fe1e74
commit
a354e5fa6b
9 changed files with 77 additions and 25 deletions
2
resources/sql/autopatches/20150223.daemon.1.id.sql
Normal file
2
resources/sql/autopatches/20150223.daemon.1.id.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_daemon.daemon_log
|
||||
ADD daemonID VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};
|
2
resources/sql/autopatches/20150223.daemon.2.idlegacy.sql
Normal file
2
resources/sql/autopatches/20150223.daemon.2.idlegacy.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
UPDATE {$NAMESPACE}_daemon.daemon_log
|
||||
SET daemonID = CONCAT('legacy-', id) WHERE daemonID = '';
|
2
resources/sql/autopatches/20150223.daemon.3.idkey.sql
Normal file
2
resources/sql/autopatches/20150223.daemon.3.idkey.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_daemon.daemon_log
|
||||
ADD UNIQUE KEY `key_daemonID` (daemonID);
|
|
@ -37,6 +37,7 @@ final class PhabricatorDaemonEventListener extends PhabricatorEventListener {
|
|||
$current_user = posix_getpwuid(posix_geteuid());
|
||||
|
||||
$daemon = id(new PhabricatorDaemonLog())
|
||||
->setDaemonID($id)
|
||||
->setDaemon($event->getValue('daemonClass'))
|
||||
->setHost(php_uname('n'))
|
||||
->setPID(getmypid())
|
||||
|
@ -114,7 +115,7 @@ final class PhabricatorDaemonEventListener extends PhabricatorEventListener {
|
|||
if (isset($this->daemons[$id])) {
|
||||
return $this->daemons[$id];
|
||||
}
|
||||
throw new Exception("No such daemon '{$id}'!");
|
||||
throw new Exception(pht('No such daemon "%s"!', $id));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,22 +37,25 @@ final class PhabricatorDaemonManagementStatusWorkflow
|
|||
$table = id(new PhutilConsoleTable())
|
||||
->addColumns(array(
|
||||
'id' => array(
|
||||
'title' => 'ID',
|
||||
'title' => pht('Log'),
|
||||
),
|
||||
'daemonID' => array(
|
||||
'title' => pht('Daemon'),
|
||||
),
|
||||
'host' => array(
|
||||
'title' => 'Host',
|
||||
'title' => pht('Host'),
|
||||
),
|
||||
'pid' => array(
|
||||
'title' => 'PID',
|
||||
'title' => pht('Overseer'),
|
||||
),
|
||||
'started' => array(
|
||||
'title' => 'Started',
|
||||
'title' => pht('Started'),
|
||||
),
|
||||
'daemon' => array(
|
||||
'title' => 'Daemon',
|
||||
'title' => pht('Class'),
|
||||
),
|
||||
'argv' => array(
|
||||
'title' => 'Arguments',
|
||||
'title' => pht('Arguments'),
|
||||
),
|
||||
));
|
||||
|
||||
|
@ -60,6 +63,7 @@ final class PhabricatorDaemonManagementStatusWorkflow
|
|||
if ($daemon instanceof PhabricatorDaemonLog) {
|
||||
$table->addRow(array(
|
||||
'id' => $daemon->getID(),
|
||||
'daemonID' => $daemon->getDaemonID(),
|
||||
'host' => $daemon->getHost(),
|
||||
'pid' => $daemon->getPID(),
|
||||
'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()),
|
||||
|
@ -76,12 +80,15 @@ final class PhabricatorDaemonManagementStatusWorkflow
|
|||
|
||||
$daemon_log = $daemon->getDaemonLog();
|
||||
$id = null;
|
||||
$daemon_id = null;
|
||||
if ($daemon_log) {
|
||||
$id = $daemon_log->getID();
|
||||
$daemon_id = $daemon_log->getDaemonID();
|
||||
}
|
||||
|
||||
$table->addRow(array(
|
||||
'id' => $id,
|
||||
'daemonID' => $daemon_id,
|
||||
'host' => 'localhost',
|
||||
'pid' => $daemon->getPID(),
|
||||
'started' => $daemon->getEpochStarted()
|
||||
|
|
|
@ -63,11 +63,15 @@ abstract class PhabricatorDaemonManagementWorkflow
|
|||
}
|
||||
}
|
||||
|
||||
$remote_daemons = id(new PhabricatorDaemonLogQuery())
|
||||
$daemon_query = id(new PhabricatorDaemonLogQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withoutIDs($local_ids)
|
||||
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
|
||||
->execute();
|
||||
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE);
|
||||
|
||||
if ($local_ids) {
|
||||
$daemon_query->withoutIDs($local_ids);
|
||||
}
|
||||
|
||||
$remote_daemons = $daemon_query->execute();
|
||||
|
||||
return array_merge($local_daemons, $remote_daemons);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ final class PhabricatorDaemonLogQuery
|
|||
private $status = self::STATUS_ALL;
|
||||
private $daemonClasses;
|
||||
private $allowStatusWrites;
|
||||
private $daemonIDs;
|
||||
|
||||
public static function getTimeUntilUnknown() {
|
||||
return 3 * PhutilDaemonHandle::getHeartbeatEventFrequency();
|
||||
|
@ -45,6 +46,11 @@ final class PhabricatorDaemonLogQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withDaemonIDs(array $daemon_ids) {
|
||||
$this->daemonIDs = $daemon_ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new PhabricatorDaemonLog();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
@ -120,14 +126,14 @@ final class PhabricatorDaemonLogQuery
|
|||
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->ids) {
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->notIDs) {
|
||||
if ($this->notIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'id NOT IN (%Ld)',
|
||||
|
@ -141,13 +147,20 @@ final class PhabricatorDaemonLogQuery
|
|||
$this->getStatusConstants());
|
||||
}
|
||||
|
||||
if ($this->daemonClasses) {
|
||||
if ($this->daemonClasses !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'daemon IN (%Ls)',
|
||||
$this->daemonClasses);
|
||||
}
|
||||
|
||||
if ($this->daemonIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'daemonID IN (%Ls)',
|
||||
$this->daemonIDs);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
return $this->formatWhereClause($where);
|
||||
}
|
||||
|
@ -165,7 +178,7 @@ final class PhabricatorDaemonLogQuery
|
|||
PhabricatorDaemonLog::STATUS_EXITING,
|
||||
);
|
||||
default:
|
||||
throw new Exception("Unknown status '{$status}'!");
|
||||
throw new Exception(pht('Unknown status "%s"!', $status));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
|
|||
protected $daemon;
|
||||
protected $host;
|
||||
protected $pid;
|
||||
protected $daemonID;
|
||||
protected $runningAsUser;
|
||||
protected $argv;
|
||||
protected $explicitArgv = array();
|
||||
|
@ -34,6 +35,7 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
|
|||
'runningAsUser' => 'text255?',
|
||||
'envHash' => 'bytes40',
|
||||
'status' => 'text8',
|
||||
'daemonID' => 'text64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'status' => array(
|
||||
|
@ -42,6 +44,10 @@ final class PhabricatorDaemonLog extends PhabricatorDaemonDAO
|
|||
'dateCreated' => array(
|
||||
'columns' => array('dateCreated'),
|
||||
),
|
||||
'key_daemonID' => array(
|
||||
'columns' => array('daemonID'),
|
||||
'unique' => true,
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,24 @@ final class PhabricatorDaemonReference {
|
|||
$refs = array();
|
||||
$daemons = idx($dict, 'daemons', array());
|
||||
|
||||
$logs = array();
|
||||
|
||||
$daemon_ids = ipull($daemons, 'id');
|
||||
if ($daemon_ids) {
|
||||
try {
|
||||
$logs = id(new PhabricatorDaemonLogQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withDaemonIDs($daemon_ids)
|
||||
->execute();
|
||||
} catch (AphrontQueryException $ex) {
|
||||
// Ignore any issues here; getting this information only allows us
|
||||
// to provide a more complete picture of daemon status, and we want
|
||||
// these commands to work if the database is inaccessible.
|
||||
}
|
||||
|
||||
$logs = mpull($logs, null, 'getDaemonID');
|
||||
}
|
||||
|
||||
foreach ($daemons as $daemon) {
|
||||
$ref = new PhabricatorDaemonReference();
|
||||
|
||||
|
@ -33,17 +51,14 @@ final class PhabricatorDaemonReference {
|
|||
$ref->pid = idx($dict, 'pid');
|
||||
$ref->start = idx($dict, 'start');
|
||||
|
||||
$ref->name = idx($daemon, 'class');
|
||||
$ref->argv = idx($daemon, 'argv', array());
|
||||
$config = idx($daemon, 'config', array());
|
||||
$ref->name = idx($config, 'class');
|
||||
$ref->argv = idx($config, 'argv', array());
|
||||
|
||||
|
||||
// TODO: We previously identified daemon logs by using a <class, pid,
|
||||
// epoch> tuple, but now all daemons under a single overseer will share
|
||||
// that identifier. We can uniquely identify daemons by $daemon['id'],
|
||||
// but that isn't currently written into the daemon logs. We should
|
||||
// start writing it, then load the logs here. This would give us a
|
||||
// slightly greater ability to keep the web UI in sync when daemons
|
||||
// get killed forcefully and clean up `phd status` a bit.
|
||||
$log = idx($logs, idx($daemon, 'id'));
|
||||
if ($log) {
|
||||
$ref->daemonLog = $log;
|
||||
}
|
||||
|
||||
$ref->pidFile = $path;
|
||||
$refs[] = $ref;
|
||||
|
|
Loading…
Reference in a new issue