1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 11:30:55 +01:00

Record lock timing information on PushEvents

Summary:
Depends on D19249. Ref T13109. Add timing information to the `PushEvent`:

  - `writeWait`: Time spent waiting for a write lock.
  - `readWait`: Time spent waiting for a read lock.
  - `hostWait`: Roughly, total time spent on the leaf node.

The primary goal here is to see if `readWait` is meaningful in the wild. If it is, that motivates smarter routing, and the value of smarter routing can be demonstrated by looking for a reduction in read wait times.

Test Plan: Pushed some stuff, saw reasonable timing values in the table. Saw timing information in "Export Data".

Maniphest Tasks: T13109

Differential Revision: https://secure.phabricator.com/D19250
This commit is contained in:
epriestley 2018-03-22 12:08:20 -07:00
parent 69bff489d4
commit df3c937dab
7 changed files with 111 additions and 17 deletions

View file

@ -0,0 +1,8 @@
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
ADD writeWait BIGINT UNSIGNED;
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
ADD readWait BIGINT UNSIGNED;
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
ADD hostWait BIGINT UNSIGNED;

View file

@ -315,12 +315,15 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
$lock_wait = phutil_units('2 minutes in seconds'); $lock_wait = phutil_units('2 minutes in seconds');
try { try {
$write_wait_start = microtime(true);
$start = PhabricatorTime::getNow(); $start = PhabricatorTime::getNow();
$step_wait = 1; $step_wait = 1;
while (true) { while (true) {
try { try {
$write_lock->lock((int)floor($step_wait)); $write_lock->lock((int)floor($step_wait));
$write_wait_end = microtime(true);
break; break;
} catch (PhutilLockException $ex) { } catch (PhutilLockException $ex) {
$waited = (PhabricatorTime::getNow() - $start); $waited = (PhabricatorTime::getNow() - $start);
@ -370,12 +373,14 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
'documentation for instructions.')); 'documentation for instructions.'));
} }
$read_wait_start = microtime(true);
try { try {
$max_version = $this->synchronizeWorkingCopyBeforeRead(); $max_version = $this->synchronizeWorkingCopyBeforeRead();
} catch (Exception $ex) { } catch (Exception $ex) {
$write_lock->unlock(); $write_lock->unlock();
throw $ex; throw $ex;
} }
$read_wait_end = microtime(true);
$pid = getmypid(); $pid = getmypid();
$hash = Filesystem::readRandomCharacters(12); $hash = Filesystem::readRandomCharacters(12);
@ -394,6 +399,15 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
$this->clusterWriteVersion = $max_version; $this->clusterWriteVersion = $max_version;
$this->clusterWriteLock = $write_lock; $this->clusterWriteLock = $write_lock;
$write_wait = ($write_wait_end - $write_wait_start);
$read_wait = ($read_wait_end - $read_wait_start);
$log = $this->logger;
if ($log) {
$log->writeClusterEngineLogProperty('readWait', $read_wait);
$log->writeClusterEngineLogProperty('writeWait', $write_wait);
}
} }

View file

@ -3,5 +3,6 @@
interface DiffusionRepositoryClusterEngineLogInterface { interface DiffusionRepositoryClusterEngineLogInterface {
public function writeClusterEngineLogMessage($message); public function writeClusterEngineLogMessage($message);
public function writeClusterEngineLogProperty($key, $value);
} }

View file

@ -14,6 +14,8 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
} }
protected function executeRepositoryOperations() { protected function executeRepositoryOperations() {
$host_wait_start = microtime(true);
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = $this->getSSHUser(); $viewer = $this->getSSHUser();
$device = AlmanacKeys::getLiveDevice(); $device = AlmanacKeys::getLiveDevice();
@ -71,6 +73,14 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
PhabricatorRepositoryStatusMessage::CODE_OKAY); PhabricatorRepositoryStatusMessage::CODE_OKAY);
$this->waitForGitClient(); $this->waitForGitClient();
$host_wait_end = microtime(true);
$this->updatePushLogWithTimingInformation(
$this->getClusterEngineLogProperty('writeWait'),
$this->getClusterEngineLogProperty('readWait'),
($host_wait_end - $host_wait_start));
} }
return $err; return $err;
@ -89,4 +99,37 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
->execute(); ->execute();
} }
private function updatePushLogWithTimingInformation(
$write_wait,
$read_wait,
$host_wait) {
if ($write_wait !== null) {
$write_wait = (int)(1000000 * $write_wait);
}
if ($read_wait !== null) {
$read_wait = (int)(1000000 * $read_wait);
}
if ($host_wait !== null) {
$host_wait = (int)(1000000 * $host_wait);
}
$identifier = $this->getRequestIdentifier();
$event = new PhabricatorRepositoryPushEvent();
$conn = $event->establishConnection('w');
queryfx(
$conn,
'UPDATE %T SET writeWait = %nd, readWait = %nd, hostWait = %nd
WHERE requestIdentifier = %s',
$event->getTableName(),
$write_wait,
$read_wait,
$host_wait,
$identifier);
}
} }

View file

@ -4,6 +4,8 @@ abstract class DiffusionGitSSHWorkflow
extends DiffusionSSHWorkflow extends DiffusionSSHWorkflow
implements DiffusionRepositoryClusterEngineLogInterface { implements DiffusionRepositoryClusterEngineLogInterface {
private $engineLogProperties = array();
protected function writeError($message) { protected function writeError($message) {
// Git assumes we'll add our own newlines. // Git assumes we'll add our own newlines.
return parent::writeError($message."\n"); return parent::writeError($message."\n");
@ -14,6 +16,14 @@ abstract class DiffusionGitSSHWorkflow
$this->getErrorChannel()->update(); $this->getErrorChannel()->update();
} }
public function writeClusterEngineLogProperty($key, $value) {
$this->engineLogProperties[$key] = $value;
}
protected function getClusterEngineLogProperty($key, $default = null) {
return idx($this->engineLogProperties, $key, $default);
}
protected function identifyRepository() { protected function identifyRepository() {
$args = $this->getArgs(); $args = $this->getArgs();
$path = head($args->getArg('dir')); $path = head($args->getArg('dir'));

View file

@ -98,57 +98,66 @@ final class PhabricatorRepositoryPushLogSearchEngine
$viewer = $this->requireViewer(); $viewer = $this->requireViewer();
$fields = array( $fields = array(
$fields[] = id(new PhabricatorIDExportField()) id(new PhabricatorIDExportField())
->setKey('pushID') ->setKey('pushID')
->setLabel(pht('Push ID')), ->setLabel(pht('Push ID')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('unique') ->setKey('unique')
->setLabel(pht('Unique')), ->setLabel(pht('Unique')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('protocol') ->setKey('protocol')
->setLabel(pht('Protocol')), ->setLabel(pht('Protocol')),
$fields[] = id(new PhabricatorPHIDExportField()) id(new PhabricatorPHIDExportField())
->setKey('repositoryPHID') ->setKey('repositoryPHID')
->setLabel(pht('Repository PHID')), ->setLabel(pht('Repository PHID')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('repository') ->setKey('repository')
->setLabel(pht('Repository')), ->setLabel(pht('Repository')),
$fields[] = id(new PhabricatorPHIDExportField()) id(new PhabricatorPHIDExportField())
->setKey('pusherPHID') ->setKey('pusherPHID')
->setLabel(pht('Pusher PHID')), ->setLabel(pht('Pusher PHID')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('pusher') ->setKey('pusher')
->setLabel(pht('Pusher')), ->setLabel(pht('Pusher')),
$fields[] = id(new PhabricatorPHIDExportField()) id(new PhabricatorPHIDExportField())
->setKey('devicePHID') ->setKey('devicePHID')
->setLabel(pht('Device PHID')), ->setLabel(pht('Device PHID')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('device') ->setKey('device')
->setLabel(pht('Device')), ->setLabel(pht('Device')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('type') ->setKey('type')
->setLabel(pht('Ref Type')), ->setLabel(pht('Ref Type')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('name') ->setKey('name')
->setLabel(pht('Ref Name')), ->setLabel(pht('Ref Name')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('old') ->setKey('old')
->setLabel(pht('Ref Old')), ->setLabel(pht('Ref Old')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('new') ->setKey('new')
->setLabel(pht('Ref New')), ->setLabel(pht('Ref New')),
$fields[] = id(new PhabricatorIntExportField()) id(new PhabricatorIntExportField())
->setKey('flags') ->setKey('flags')
->setLabel(pht('Flags')), ->setLabel(pht('Flags')),
$fields[] = id(new PhabricatorStringListExportField()) id(new PhabricatorStringListExportField())
->setKey('flagNames') ->setKey('flagNames')
->setLabel(pht('Flag Names')), ->setLabel(pht('Flag Names')),
$fields[] = id(new PhabricatorIntExportField()) id(new PhabricatorIntExportField())
->setKey('result') ->setKey('result')
->setLabel(pht('Result')), ->setLabel(pht('Result')),
$fields[] = id(new PhabricatorStringExportField()) id(new PhabricatorStringExportField())
->setKey('resultName') ->setKey('resultName')
->setLabel(pht('Result Name')), ->setLabel(pht('Result Name')),
id(new PhabricatorIntExportField())
->setKey('writeWait')
->setLabel(pht('Write Wait (us)')),
id(new PhabricatorIntExportField())
->setKey('readWait')
->setLabel(pht('Read Wait (us)')),
id(new PhabricatorIntExportField())
->setKey('hostWait')
->setLabel(pht('Host Wait (us)')),
); );
if ($viewer->getIsAdmin()) { if ($viewer->getIsAdmin()) {
@ -228,6 +237,9 @@ final class PhabricatorRepositoryPushLogSearchEngine
'flagNames' => $flag_names, 'flagNames' => $flag_names,
'result' => $result, 'result' => $result,
'resultName' => $result_name, 'resultName' => $result_name,
'writeWait' => $event->getWriteWait(),
'readWait' => $event->getReadWait(),
'hostWait' => $event->getHostWait(),
); );
if ($viewer->getIsAdmin()) { if ($viewer->getIsAdmin()) {

View file

@ -16,6 +16,9 @@ final class PhabricatorRepositoryPushEvent
protected $remoteProtocol; protected $remoteProtocol;
protected $rejectCode; protected $rejectCode;
protected $rejectDetails; protected $rejectDetails;
protected $writeWait;
protected $readWait;
protected $hostWait;
private $repository = self::ATTACHABLE; private $repository = self::ATTACHABLE;
private $logs = self::ATTACHABLE; private $logs = self::ATTACHABLE;
@ -35,6 +38,9 @@ final class PhabricatorRepositoryPushEvent
'remoteProtocol' => 'text32?', 'remoteProtocol' => 'text32?',
'rejectCode' => 'uint32', 'rejectCode' => 'uint32',
'rejectDetails' => 'text64?', 'rejectDetails' => 'text64?',
'writeWait' => 'uint64?',
'readWait' => 'uint64?',
'hostWait' => 'uint64?',
), ),
self::CONFIG_KEY_SCHEMA => array( self::CONFIG_KEY_SCHEMA => array(
'key_repository' => array( 'key_repository' => array(