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

Generate a random unique "Request ID" for SSH requests so processes can coordinate better

Summary:
Depends on D19247. Ref T13109. When we receive an SSH request, generate a random unique ID for the request. Then thread it down through the process tree.

The immediate goal is to let the `ssh-exec` process coordinate with `commit-hook` process and log information about read and write lock wait times. Today, there's no way for `ssh-exec` to interact with the `PushEvent`, but this is the most helpful place to store this data for users.

Test Plan: Made pushes, saw the `PushEvent` table populate with a random request ID. Exported data and saw the ID preserved in the export.

Maniphest Tasks: T13109

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

+69 -3
+5
resources/sql/autopatches/20180322.lock.01.identifier.sql
··· 1 + ALTER TABLE {$NAMESPACE}_repository.repository_pushevent 2 + ADD requestIdentifier VARBINARY(12); 3 + 4 + ALTER TABLE {$NAMESPACE}_repository.repository_pushevent 5 + ADD UNIQUE KEY `key_request` (requestIdentifier);
+5
scripts/repository/commit_hook.php
··· 187 187 $engine->setRemoteProtocol($remote_protocol); 188 188 } 189 189 190 + $request_identifier = getenv(DiffusionCommitHookEngine::ENV_REQUEST); 191 + if (strlen($request_identifier)) { 192 + $engine->setRequestIdentifier($request_identifier); 193 + } 194 + 190 195 try { 191 196 $err = $engine->execute(); 192 197 } catch (DiffusionCommitHookRejectException $ex) {
+7
scripts/ssh/ssh-exec.php
··· 8 8 9 9 $ssh_log = PhabricatorSSHLog::getLog(); 10 10 11 + $request_identifier = Filesystem::readRandomCharacters(12); 12 + $ssh_log->setData( 13 + array( 14 + 'Q' => $request_identifier, 15 + )); 16 + 11 17 $args = new PhutilArgumentParser($argv); 12 18 $args->setTagline(pht('execute SSH requests')); 13 19 $args->setSynopsis(<<<EOSYNOPSIS ··· 248 254 $workflow->setSSHUser($user); 249 255 $workflow->setOriginalArguments($original_argv); 250 256 $workflow->setIsClusterRequest($is_cluster_request); 257 + $workflow->setRequestIdentifier($request_identifier); 251 258 252 259 $sock_stdin = fopen('php://stdin', 'r'); 253 260 if (!$sock_stdin) {
+4
src/applications/config/option/PhabricatorAccessLogConfigOptions.php
··· 47 47 's' => pht('The system user.'), 48 48 'S' => pht('The system sudo user.'), 49 49 'k' => pht('ID of the SSH key used to authenticate the request.'), 50 + 51 + // TODO: This is a reasonable thing to support in the HTTP access 52 + // log, too. 53 + 'Q' => pht('A random, unique string which identifies the request.'), 50 54 ); 51 55 52 56 $http_desc = pht(
+23 -3
src/applications/diffusion/engine/DiffusionCommitHookEngine.php
··· 12 12 13 13 const ENV_REPOSITORY = 'PHABRICATOR_REPOSITORY'; 14 14 const ENV_USER = 'PHABRICATOR_USER'; 15 + const ENV_REQUEST = 'PHABRICATOR_REQUEST'; 15 16 const ENV_REMOTE_ADDRESS = 'PHABRICATOR_REMOTE_ADDRESS'; 16 17 const ENV_REMOTE_PROTOCOL = 'PHABRICATOR_REMOTE_PROTOCOL'; 17 18 ··· 25 26 private $subversionRepository; 26 27 private $remoteAddress; 27 28 private $remoteProtocol; 29 + private $requestIdentifier; 28 30 private $transactionKey; 29 31 private $mercurialHook; 30 32 private $mercurialCommits = array(); ··· 56 58 57 59 public function getRemoteAddress() { 58 60 return $this->remoteAddress; 61 + } 62 + 63 + public function setRequestIdentifier($request_identifier) { 64 + $this->requestIdentifier = $request_identifier; 65 + return $this; 66 + } 67 + 68 + public function getRequestIdentifier() { 69 + return $this->requestIdentifier; 59 70 } 60 71 61 72 public function setSubversionTransactionInfo($transaction, $repository) { ··· 620 631 $env = array( 621 632 self::ENV_REPOSITORY => $this->getRepository()->getPHID(), 622 633 self::ENV_USER => $this->getViewer()->getUsername(), 634 + self::ENV_REQUEST => $this->getRequestIdentifier(), 623 635 self::ENV_REMOTE_PROTOCOL => $this->getRemoteProtocol(), 624 636 self::ENV_REMOTE_ADDRESS => $this->getRemoteAddress(), 625 637 ); ··· 1081 1093 ->setDevicePHID($device_phid) 1082 1094 ->setRepositoryPHID($this->getRepository()->getPHID()) 1083 1095 ->attachRepository($this->getRepository()) 1084 - ->setEpoch(time()); 1096 + ->setEpoch(PhabricatorTime::getNow()); 1085 1097 } 1086 1098 1087 1099 private function newPushEvent() { 1088 1100 $viewer = $this->getViewer(); 1089 - return PhabricatorRepositoryPushEvent::initializeNewEvent($viewer) 1101 + 1102 + $event = PhabricatorRepositoryPushEvent::initializeNewEvent($viewer) 1090 1103 ->setRepositoryPHID($this->getRepository()->getPHID()) 1091 1104 ->setRemoteAddress($this->getRemoteAddress()) 1092 1105 ->setRemoteProtocol($this->getRemoteProtocol()) 1093 - ->setEpoch(time()); 1106 + ->setEpoch(PhabricatorTime::getNow()); 1107 + 1108 + $identifier = $this->getRequestIdentifier(); 1109 + if (strlen($identifier)) { 1110 + $event->setRequestIdentifier($identifier); 1111 + } 1112 + 1113 + return $event; 1094 1114 } 1095 1115 1096 1116 private function rejectEnormousChanges(array $content_updates) {
+5
src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
··· 30 30 DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL => 'ssh', 31 31 ); 32 32 33 + $identifier = $this->getRequestIdentifier(); 34 + if ($identifier !== null) { 35 + $env[DiffusionCommitHookEngine::ENV_REQUEST] = $identifier; 36 + } 37 + 33 38 $remote_address = $this->getSSHRemoteAddress(); 34 39 if ($remote_address !== null) { 35 40 $env[DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS] = $remote_address;
+4
src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php
··· 102 102 ->setKey('pushID') 103 103 ->setLabel(pht('Push ID')), 104 104 $fields[] = id(new PhabricatorStringExportField()) 105 + ->setKey('unique') 106 + ->setLabel(pht('Unique')), 107 + $fields[] = id(new PhabricatorStringExportField()) 105 108 ->setKey('protocol') 106 109 ->setLabel(pht('Protocol')), 107 110 $fields[] = id(new PhabricatorPHIDExportField()) ··· 209 212 210 213 $map = array( 211 214 'pushID' => $event->getID(), 215 + 'unique' => $event->getRequestIdentifier(), 212 216 'protocol' => $event->getRemoteProtocol(), 213 217 'repositoryPHID' => $repository_phid, 214 218 'repository' => $repository_name,
+6
src/applications/repository/storage/PhabricatorRepositoryPushEvent.php
··· 11 11 protected $repositoryPHID; 12 12 protected $epoch; 13 13 protected $pusherPHID; 14 + protected $requestIdentifier; 14 15 protected $remoteAddress; 15 16 protected $remoteProtocol; 16 17 protected $rejectCode; ··· 29 30 self::CONFIG_AUX_PHID => true, 30 31 self::CONFIG_TIMESTAMPS => false, 31 32 self::CONFIG_COLUMN_SCHEMA => array( 33 + 'requestIdentifier' => 'bytes12?', 32 34 'remoteAddress' => 'ipaddress?', 33 35 'remoteProtocol' => 'text32?', 34 36 'rejectCode' => 'uint32', ··· 37 39 self::CONFIG_KEY_SCHEMA => array( 38 40 'key_repository' => array( 39 41 'columns' => array('repositoryPHID'), 42 + ), 43 + 'key_request' => array( 44 + 'columns' => array('requestIdentifier'), 45 + 'unique' => true, 40 46 ), 41 47 ), 42 48 ) + parent::getConfiguration();
+10
src/infrastructure/ssh/PhabricatorSSHWorkflow.php
··· 13 13 private $errorChannel; 14 14 private $isClusterRequest; 15 15 private $originalArguments; 16 + private $requestIdentifier; 16 17 17 18 public function isExecutable() { 18 19 return false; ··· 87 88 88 89 public function getOriginalArguments() { 89 90 return $this->originalArguments; 91 + } 92 + 93 + public function setRequestIdentifier($request_identifier) { 94 + $this->requestIdentifier = $request_identifier; 95 + return $this; 96 + } 97 + 98 + public function getRequestIdentifier() { 99 + return $this->requestIdentifier; 90 100 } 91 101 92 102 public function getSSHRemoteAddress() {