1
0
Fork 0
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:
epriestley 2015-02-23 11:26:38 -08:00
parent ef22fe1e74
commit a354e5fa6b
9 changed files with 77 additions and 25 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_daemon.daemon_log
ADD daemonID VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,2 @@
UPDATE {$NAMESPACE}_daemon.daemon_log
SET daemonID = CONCAT('legacy-', id) WHERE daemonID = '';

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_daemon.daemon_log
ADD UNIQUE KEY `key_daemonID` (daemonID);

View file

@ -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));
}
}

View file

@ -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()

View file

@ -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);
}

View file

@ -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));
}
}

View file

@ -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();
}

View file

@ -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;