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

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

+77 -25
+2
resources/sql/autopatches/20150223.daemon.1.id.sql
··· 1 + ALTER TABLE {$NAMESPACE}_daemon.daemon_log 2 + ADD daemonID VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};
+2
resources/sql/autopatches/20150223.daemon.2.idlegacy.sql
··· 1 + UPDATE {$NAMESPACE}_daemon.daemon_log 2 + SET daemonID = CONCAT('legacy-', id) WHERE daemonID = '';
+2
resources/sql/autopatches/20150223.daemon.3.idkey.sql
··· 1 + ALTER TABLE {$NAMESPACE}_daemon.daemon_log 2 + ADD UNIQUE KEY `key_daemonID` (daemonID);
+2 -1
src/applications/daemon/event/PhabricatorDaemonEventListener.php
··· 37 37 $current_user = posix_getpwuid(posix_geteuid()); 38 38 39 39 $daemon = id(new PhabricatorDaemonLog()) 40 + ->setDaemonID($id) 40 41 ->setDaemon($event->getValue('daemonClass')) 41 42 ->setHost(php_uname('n')) 42 43 ->setPID(getmypid()) ··· 114 115 if (isset($this->daemons[$id])) { 115 116 return $this->daemons[$id]; 116 117 } 117 - throw new Exception("No such daemon '{$id}'!"); 118 + throw new Exception(pht('No such daemon "%s"!', $id)); 118 119 } 119 120 120 121 }
+13 -6
src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php
··· 37 37 $table = id(new PhutilConsoleTable()) 38 38 ->addColumns(array( 39 39 'id' => array( 40 - 'title' => 'ID', 40 + 'title' => pht('Log'), 41 + ), 42 + 'daemonID' => array( 43 + 'title' => pht('Daemon'), 41 44 ), 42 45 'host' => array( 43 - 'title' => 'Host', 46 + 'title' => pht('Host'), 44 47 ), 45 48 'pid' => array( 46 - 'title' => 'PID', 49 + 'title' => pht('Overseer'), 47 50 ), 48 51 'started' => array( 49 - 'title' => 'Started', 52 + 'title' => pht('Started'), 50 53 ), 51 54 'daemon' => array( 52 - 'title' => 'Daemon', 55 + 'title' => pht('Class'), 53 56 ), 54 57 'argv' => array( 55 - 'title' => 'Arguments', 58 + 'title' => pht('Arguments'), 56 59 ), 57 60 )); 58 61 ··· 60 63 if ($daemon instanceof PhabricatorDaemonLog) { 61 64 $table->addRow(array( 62 65 'id' => $daemon->getID(), 66 + 'daemonID' => $daemon->getDaemonID(), 63 67 'host' => $daemon->getHost(), 64 68 'pid' => $daemon->getPID(), 65 69 'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()), ··· 76 80 77 81 $daemon_log = $daemon->getDaemonLog(); 78 82 $id = null; 83 + $daemon_id = null; 79 84 if ($daemon_log) { 80 85 $id = $daemon_log->getID(); 86 + $daemon_id = $daemon_log->getDaemonID(); 81 87 } 82 88 83 89 $table->addRow(array( 84 90 'id' => $id, 91 + 'daemonID' => $daemon_id, 85 92 'host' => 'localhost', 86 93 'pid' => $daemon->getPID(), 87 94 'started' => $daemon->getEpochStarted()
+8 -4
src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
··· 63 63 } 64 64 } 65 65 66 - $remote_daemons = id(new PhabricatorDaemonLogQuery()) 66 + $daemon_query = id(new PhabricatorDaemonLogQuery()) 67 67 ->setViewer(PhabricatorUser::getOmnipotentUser()) 68 - ->withoutIDs($local_ids) 69 - ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) 70 - ->execute(); 68 + ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE); 69 + 70 + if ($local_ids) { 71 + $daemon_query->withoutIDs($local_ids); 72 + } 73 + 74 + $remote_daemons = $daemon_query->execute(); 71 75 72 76 return array_merge($local_daemons, $remote_daemons); 73 77 }
+17 -4
src/applications/daemon/query/PhabricatorDaemonLogQuery.php
··· 11 11 private $status = self::STATUS_ALL; 12 12 private $daemonClasses; 13 13 private $allowStatusWrites; 14 + private $daemonIDs; 14 15 15 16 public static function getTimeUntilUnknown() { 16 17 return 3 * PhutilDaemonHandle::getHeartbeatEventFrequency(); ··· 42 43 43 44 public function setAllowStatusWrites($allow) { 44 45 $this->allowStatusWrites = $allow; 46 + return $this; 47 + } 48 + 49 + public function withDaemonIDs(array $daemon_ids) { 50 + $this->daemonIDs = $daemon_ids; 45 51 return $this; 46 52 } 47 53 ··· 120 126 private function buildWhereClause(AphrontDatabaseConnection $conn_r) { 121 127 $where = array(); 122 128 123 - if ($this->ids) { 129 + if ($this->ids !== null) { 124 130 $where[] = qsprintf( 125 131 $conn_r, 126 132 'id IN (%Ld)', 127 133 $this->ids); 128 134 } 129 135 130 - if ($this->notIDs) { 136 + if ($this->notIDs !== null) { 131 137 $where[] = qsprintf( 132 138 $conn_r, 133 139 'id NOT IN (%Ld)', ··· 141 147 $this->getStatusConstants()); 142 148 } 143 149 144 - if ($this->daemonClasses) { 150 + if ($this->daemonClasses !== null) { 145 151 $where[] = qsprintf( 146 152 $conn_r, 147 153 'daemon IN (%Ls)', 148 154 $this->daemonClasses); 155 + } 156 + 157 + if ($this->daemonIDs !== null) { 158 + $where[] = qsprintf( 159 + $conn_r, 160 + 'daemonID IN (%Ls)', 161 + $this->daemonIDs); 149 162 } 150 163 151 164 $where[] = $this->buildPagingClause($conn_r); ··· 165 178 PhabricatorDaemonLog::STATUS_EXITING, 166 179 ); 167 180 default: 168 - throw new Exception("Unknown status '{$status}'!"); 181 + throw new Exception(pht('Unknown status "%s"!', $status)); 169 182 } 170 183 } 171 184
+6
src/applications/daemon/storage/PhabricatorDaemonLog.php
··· 13 13 protected $daemon; 14 14 protected $host; 15 15 protected $pid; 16 + protected $daemonID; 16 17 protected $runningAsUser; 17 18 protected $argv; 18 19 protected $explicitArgv = array(); ··· 34 35 'runningAsUser' => 'text255?', 35 36 'envHash' => 'bytes40', 36 37 'status' => 'text8', 38 + 'daemonID' => 'text64', 37 39 ), 38 40 self::CONFIG_KEY_SCHEMA => array( 39 41 'status' => array( ··· 41 43 ), 42 44 'dateCreated' => array( 43 45 'columns' => array('dateCreated'), 46 + ), 47 + 'key_daemonID' => array( 48 + 'columns' => array('daemonID'), 49 + 'unique' => true, 44 50 ), 45 51 ), 46 52 ) + parent::getConfiguration();
+25 -10
src/infrastructure/daemon/control/PhabricatorDaemonReference.php
··· 22 22 $refs = array(); 23 23 $daemons = idx($dict, 'daemons', array()); 24 24 25 + $logs = array(); 26 + 27 + $daemon_ids = ipull($daemons, 'id'); 28 + if ($daemon_ids) { 29 + try { 30 + $logs = id(new PhabricatorDaemonLogQuery()) 31 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 32 + ->withDaemonIDs($daemon_ids) 33 + ->execute(); 34 + } catch (AphrontQueryException $ex) { 35 + // Ignore any issues here; getting this information only allows us 36 + // to provide a more complete picture of daemon status, and we want 37 + // these commands to work if the database is inaccessible. 38 + } 39 + 40 + $logs = mpull($logs, null, 'getDaemonID'); 41 + } 42 + 25 43 foreach ($daemons as $daemon) { 26 44 $ref = new PhabricatorDaemonReference(); 27 45 ··· 33 51 $ref->pid = idx($dict, 'pid'); 34 52 $ref->start = idx($dict, 'start'); 35 53 36 - $ref->name = idx($daemon, 'class'); 37 - $ref->argv = idx($daemon, 'argv', array()); 54 + $config = idx($daemon, 'config', array()); 55 + $ref->name = idx($config, 'class'); 56 + $ref->argv = idx($config, 'argv', array()); 38 57 39 - 40 - // TODO: We previously identified daemon logs by using a <class, pid, 41 - // epoch> tuple, but now all daemons under a single overseer will share 42 - // that identifier. We can uniquely identify daemons by $daemon['id'], 43 - // but that isn't currently written into the daemon logs. We should 44 - // start writing it, then load the logs here. This would give us a 45 - // slightly greater ability to keep the web UI in sync when daemons 46 - // get killed forcefully and clean up `phd status` a bit. 58 + $log = idx($logs, idx($daemon, 'id')); 59 + if ($log) { 60 + $ref->daemonLog = $log; 61 + } 47 62 48 63 $ref->pidFile = $path; 49 64 $refs[] = $ref;