1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 14:00:56 +01:00

Support sampling subprocess execution in Multimeter

Summary: Ref T6930. Add subprocess sampling/labeling.

Test Plan:
(This table includes some buggy test labels.)

{F391655}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T6930

Differential Revision: https://secure.phabricator.com/D12675
This commit is contained in:
epriestley 2015-05-04 10:06:23 -07:00
parent e6e0df6aff
commit bee4dc7d53
2 changed files with 90 additions and 1 deletions

View file

@ -91,6 +91,8 @@ final class MultimeterControl {
throw new Exception(pht('Call setSampleRate() before saving events!')); throw new Exception(pht('Call setSampleRate() before saving events!'));
} }
$this->addServiceEvents();
// Don't sample any of this stuff. // Don't sample any of this stuff.
$this->pauseMultimeter(); $this->pauseMultimeter();
@ -191,7 +193,7 @@ final class MultimeterControl {
if (isset($map[$name])) { if (isset($map[$name])) {
continue; continue;
} }
$need[] = $name; $need[$name] = $name;
} }
foreach ($need as $name) { foreach ($need as $name) {
@ -204,4 +206,87 @@ final class MultimeterControl {
return $map; return $map;
} }
private function addServiceEvents() {
$events = PhutilServiceProfiler::getInstance()->getServiceCallLog();
foreach ($events as $event) {
$type = idx($event, 'type');
switch ($type) {
case 'exec':
$this->newEvent(
MultimeterEvent::TYPE_EXEC_TIME,
$label = $this->getLabelForCommandEvent($event['command']),
(1000000 * $event['duration']));
break;
}
}
}
private function getLabelForCommandEvent($command) {
$argv = preg_split('/\s+/', $command);
$bin = array_shift($argv);
$bin = basename($bin);
$bin = trim($bin, '"\'');
// It's important to avoid leaking details about command parameters,
// because some may be sensitive. Given this, it's not trivial to
// determine which parts of a command are arguments and which parts are
// flags.
// Rather than try too hard for now, just whitelist some workflows that we
// know about and record everything else generically. Overall, this will
// produce labels like "pygmentize" or "git log", discarding all flags and
// arguments.
$workflows = array(
'git' => array(
'log' => true,
'for-each-ref' => true,
'pull' => true,
'clone' => true,
'fetch' => true,
'cat-file' => true,
'init' => true,
'config' => true,
'remote' => true,
'rev-parse' => true,
'diff' => true,
'ls-tree' => true,
),
'svn' => array(
'log' => true,
'diff' => true,
),
'hg' => array(
'log' => true,
'locate' => true,
'pull' => true,
'clone' => true,
'init' => true,
'diff' => true,
'cat' => true,
),
'svnadmin' => array(
'create' => true,
),
);
$workflow = null;
$candidates = idx($workflows, $bin);
if ($candidates) {
foreach ($argv as $arg) {
if (isset($candidates[$arg])) {
$workflow = $arg;
break;
}
}
}
if ($workflow) {
return 'bin.'.$bin.' '.$workflow;
} else {
return 'bin.'.$bin;
}
}
} }

View file

@ -4,6 +4,7 @@ final class MultimeterEvent extends MultimeterDAO {
const TYPE_STATIC_RESOURCE = 0; const TYPE_STATIC_RESOURCE = 0;
const TYPE_REQUEST_TIME = 1; const TYPE_REQUEST_TIME = 1;
const TYPE_EXEC_TIME = 2;
protected $eventType; protected $eventType;
protected $eventLabelID; protected $eventLabelID;
@ -32,6 +33,8 @@ final class MultimeterEvent extends MultimeterDAO {
return pht('Static Resource'); return pht('Static Resource');
case self::TYPE_REQUEST_TIME: case self::TYPE_REQUEST_TIME:
return pht('Web Request'); return pht('Web Request');
case self::TYPE_EXEC_TIME:
return pht('Subprocesses');
} }
return pht('Unknown ("%s")', $type); return pht('Unknown ("%s")', $type);
@ -46,6 +49,7 @@ final class MultimeterEvent extends MultimeterDAO {
case self::TYPE_STATIC_RESOURCE: case self::TYPE_STATIC_RESOURCE:
return pht('%s Req', new PhutilNumber($cost)); return pht('%s Req', new PhutilNumber($cost));
case self::TYPE_REQUEST_TIME: case self::TYPE_REQUEST_TIME:
case self::TYPE_EXEC_TIME:
return pht('%s us', new PhutilNumber($cost)); return pht('%s us', new PhutilNumber($cost));
} }